accept no compromises

Rudimentary Runtracer For Windows 7

Rudimentary Runtracer For Windows 7
Posted Aug 29, 2012
Authored by JODE | Site nsense.net

This is a rudimentary runtracer for Windows 7 on x86 (ASLR resilient).

tags | x86
systems | windows, 7
MD5 | 352a3526fd4ae1480860ad14025a617c

Rudimentary Runtracer For Windows 7

Change Mirror Download
// Blocks the c version
// http://nsense.net
// Joakim "JODE" Sandström
//
// Description: Dumb runtracing. Sorry about the messy code - it reflects the inside of my head.
// Platform: Win7 x86
//

#include <windows.h>
#include <Dbghelp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <psapi.h>
#include <time.h>
#include <map>
#include <string>
#include <set>

#include "distorm.h"
using namespace std;

#pragma comment(lib, "distorm.lib")

//#define VERBOSE "on" // enable to get debug outputs.
#define showUsage() printf("-[Blocks by nSense 2011\n Usage: blocks.exe -f filename -p param -o output -w delay")

typedef struct _ModuleInfo {
char FileName[MAX_PATH];
long lBase;
long lCodeMaxAddress;
bool bDll;
long lSizeOfCode;
unsigned char* PCodeCache;
} *PModuleInfo;


// The number of the array of instructions the decoder function will use to return the disassembled instructions.
// Play with this value for performance...
#define MAX_INSTRUCTIONS (100)
#define BUFSIZE 512

DWORD dwContinueStatus = DBG_CONTINUE;
std::map<LPVOID, std::string> DllNameMap;
std::map<long, unsigned int> OrginalBytesCache;
std::map<long, _DInst> BranchingDynamicRegister;
std::map<long, long> BackFlowLocation;
set<long>BackFlowOffset;
set<long>AnalyzedBreakPoints;
set<long>KnownBreakPoints;
set<long>AnalyzedOffsets;
set<long>BranchingDynamicBreakPoint;
set<long>VisitedBreakPoints;

IMAGE_NT_HEADERS I_NT;
HMODULE *hmodules = 0;
PROCESS_INFORMATION ProcessInformation;
STARTUPINFO StartupInfo;

bool bContinueDebugging = true;
bool HasAnalyzedEntryPoint = false;
char OutputFileName[MAX_PATH];
long ModuleCount = 0;
int TimeOut;
PModuleInfo tracedmodules = new _ModuleInfo[MAX_PATH];

void EnableDebugPriv() {

HANDLE hToken;
LUID luid;
TOKEN_PRIVILEGES tkp;

OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken );

LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &luid );

tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = luid;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

AdjustTokenPrivileges( hToken, false, &tkp, sizeof( tkp ), NULL, NULL );

CloseHandle( hToken );
}


char* GetFileNameFromHandle(HANDLE hFile)
{
BOOL bSuccess = FALSE;
TCHAR pszFilename[MAX_PATH+1];
HANDLE hFileMap;

char strFilename[MAX_PATH];
memset(strFilename,NULL, sizeof(strFilename));

// Get the file size.
DWORD dwFileSizeHi = 0;
DWORD dwFileSizeLo = GetFileSize(hFile, &dwFileSizeHi);

if( dwFileSizeLo == 0 && dwFileSizeHi == 0 )
return FALSE;

// Create a file mapping object.
hFileMap = CreateFileMapping(hFile,
NULL,
PAGE_READONLY,
0,
1,
NULL);

if (hFileMap)
{
// Create a file mapping to get the file name.
void* pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1);

if (pMem)
{
if (GetMappedFileName(GetCurrentProcess(),
pMem,
pszFilename,
MAX_PATH))
{

// Translate path with device name to drive letters.
TCHAR szTemp[BUFSIZE];
szTemp[0] = '\0';

if (GetLogicalDriveStrings(BUFSIZE-1, szTemp))
{
TCHAR szName[MAX_PATH];
TCHAR szDrive[3] = TEXT(" :");
BOOL bFound = FALSE;
TCHAR* p = szTemp;

do
{
// Copy the drive letter to the template string
*szDrive = *p;

if (QueryDosDevice(szDrive, szName, MAX_PATH))
{
size_t uNameLen = strlen(szName);

if (uNameLen < MAX_PATH)
{
bFound = strncmp(pszFilename, szName, uNameLen) == 0;

if (bFound)
sprintf(strFilename,"%s%s",szDrive, pszFilename+uNameLen);
}
}
while (*p++);
} while (!bFound && *p); // end of string
}
}
bSuccess = TRUE;
UnmapViewOfFile(pMem);
}

CloseHandle(hFileMap);
}

return(strFilename);
}


bool InScope(unsigned long absolute_target_address){

// notice the isdll (can be used to limit depth - in future)
for(int ii = 0;ii<ModuleCount;ii++){
if(tracedmodules[ii].lBase < absolute_target_address && absolute_target_address < tracedmodules[ii].lCodeMaxAddress && tracedmodules[ii].bDll == false)
return true;
}

#ifdef VERBOSE
printf("Inscope: not in scope: %x\n", abosulte_target_address);
#endif

return false;
}

void RemoveBreakPoint(long absoluteoffset, DWORD dwThreadId)
{
unsigned int obyte= OrginalBytesCache[(long)absoluteoffset];
CONTEXT ctx;

HANDLE th = OpenThread(THREAD_ALL_ACCESS, NULL, dwThreadId);
ctx.ContextFlags = CONTEXT_CONTROL;
GetThreadContext(th, &ctx);
ctx.Eip = (DWORD)absoluteoffset;
SetThreadContext(th, &ctx);
DWORD oprot;
VirtualProtect((LPVOID)absoluteoffset, 1, PAGE_EXECUTE_READWRITE, &oprot);

unsigned char byte[1] = {obyte};
WriteProcessMemory(ProcessInformation.hProcess,(LPVOID) absoluteoffset,(LPCVOID) byte, 1, 0);
VirtualProtect((LPVOID)absoluteoffset, 1, oprot,0);

#ifdef VERBOSE
printf("Removing bp.. %x\n", absoluteoffset);
#endif

CloseHandle(th);
FlushInstructionCache(ProcessInformation.hProcess,(LPVOID)absoluteoffset,1);

}

void SetBreakPoint(long absolute_offset){

set<long>::iterator it;
it = KnownBreakPoints.find(absolute_offset);
if(it!=KnownBreakPoints.end())
return;

unsigned char opcode;
ReadProcessMemory(ProcessInformation.hProcess,(LPCVOID)absolute_offset, &opcode, 1, 0);
if(opcode!=0xCC){
OrginalBytesCache.insert(std::make_pair((long)absolute_offset,opcode));
DWORD oldprot;
VirtualProtect((LPVOID)absolute_offset, 1, PAGE_EXECUTE_READWRITE, &oldprot);
WriteProcessMemory(ProcessInformation.hProcess,(LPVOID) absolute_offset, "\xCC",1,0);
VirtualProtect((LPVOID)absolute_offset, 1, oldprot,0);
FlushInstructionCache(ProcessInformation.hProcess,(LPCVOID)absolute_offset,1);
KnownBreakPoints.insert(absolute_offset);
#ifdef VERBOSE
printf("--> SET BP %x:\n",absolute_offset);
#endif
}

}
void Analyze(long absoluteoffset, DWORD dwThreadId){

_OffsetType offset = absoluteoffset-I_NT.OptionalHeader.BaseOfCode;
unsigned char *buf =NULL;
_ModuleInfo curmodule;

#ifdef VERBOSE
printf("attempting to analyze %x\n", absoluteoffset);
#endif

// detect in which module the breakpoint is located and loadup needed data + code
for(int ii = 0;ii<ModuleCount;ii++){
if(tracedmodules[ii].lBase < absoluteoffset && absoluteoffset < tracedmodules[ii].lCodeMaxAddress){
offset = absoluteoffset - tracedmodules[ii].lBase;// - tracedmodules[ii].lBase;
curmodule = tracedmodules[ii];
buf = tracedmodules[ii].PCodeCache;
break;
}
}

if(buf==NULL){
printf("error code not found..\n");
return;
}

buf += offset;
_CodeInfo ci = {0};
ci.code = buf;
ci.codeLen = curmodule.lSizeOfCode - offset;
ci.dt = Decode32Bits;
ci.codeOffset = offset;
ci.features = DF_STOP_ON_RET;

_DInst result[8096];

unsigned int instructions_count = 0;
set<long>::iterator it;

distorm_decompose(&ci, result, sizeof(result)/sizeof(result[0]), &instructions_count);
it = AnalyzedOffsets.find(curmodule.lBase+result[0].addr);
if(it!=AnalyzedOffsets.end())
return;

#ifdef VERBOSE
else
printf("--> Section TOP: %x\n", absoluteoffset);
#endif

for (unsigned int i = 0; i < instructions_count; i++) {

it = AnalyzedOffsets.find(curmodule.lBase+result[i].addr);
if(it!=AnalyzedOffsets.end())
return;
else
AnalyzedOffsets.insert(curmodule.lBase+result[i].addr);

if (result[i].flags == FLAG_NOT_DECODABLE){
printf("Unable to decode at %x\n", curmodule.lBase+result[i].addr);
return;
}

_DecodedInst inst;
distorm_format(&ci, &result[i], &inst);

#ifdef VERBOSE
printf("%x,",curmodule.lBase+result[i].addr);
printf("%s %s\n", inst.mnemonic.p, inst.operands.p);
printf("%x\n", result[i].opcode);
#endif

long absoluteoffset = curmodule.lBase+result[i].addr;

if (META_GET_FC(result[i].meta) == FC_CALL || META_GET_FC(result[i].meta) == FC_UNC_BRANCH || META_GET_FC(result[i].meta) == FC_CND_BRANCH)
{
_OffsetType absolute_target_address = 0;

// if you have a dll causing problems you can limit the loadup here to debug it
if(result[i].ops[0].type == O_REG || result[i].ops[0].type == O_DISP || result[i].ops[0].type == O_SMEM || result[i].ops[0].type == O_MEM || result[i].ops[0].type==O_DISP || result[i].ops[0].type==O_PC ){

// ops[0].index
// 16=eax;22=esi;23=edi;19=ebx;21=ebp;18=edx;17=ecx
it = BranchingDynamicBreakPoint.find(absoluteoffset);
if(it==BranchingDynamicBreakPoint.end()){
BranchingDynamicBreakPoint.insert(absoluteoffset);
BranchingDynamicRegister.insert(std::make_pair(absoluteoffset, result[i]));
SetBreakPoint(absoluteoffset);
return;
}

// compile optimizations?
if(META_GET_FC(result[i].meta)==FC_UNC_BRANCH)
return;
}
}

if (META_GET_FC(result[i].meta) == FC_RET){
#ifdef VERBOSE
printf("\nret found %x\n",(result[i].addr+curmodule.lBase) );
#endif
return;
}
}
return;
}

void GetModuleInfo()
{
DWORD needed = 0;
MODULEINFO mi;
// we know this from dllload events but yeh..
EnumProcessModules(ProcessInformation.hProcess, hmodules, 0, &needed);
hmodules = new HMODULE[needed/sizeof(HMODULE)];
EnumProcessModules(ProcessInformation.hProcess, hmodules, needed, &needed);

for (unsigned int i=0; i<needed/4; ++i)
GetModuleInformation(ProcessInformation.hProcess, hmodules[i], &mi, sizeof(mi));

}

long readreg(CONTEXT *ctx, long index){

long tooffset = 0;
switch(index){
case 16:
tooffset = ctx->Eax;
break;
case 22:
tooffset = ctx->Esi;
break;
case 23:
tooffset = ctx->Edi;
break;
case 19:
tooffset = ctx->Ebx;
break;
case 21:
tooffset = ctx->Ebp;
break;
case 18:
tooffset = ctx->Edx;
break;
case 17:
tooffset = ctx->Ecx;
break;
default:
printf("could not find dyn register data");

}

return tooffset;
}

void AnalyzeException(long offset, DWORD dwThreadId)
{
set<long>::iterator it;
_ModuleInfo ActualModule;

unsigned long iModuleNum = 0;
// detect in which module the breakpoint is located and loadup needed data + code
for(int ii = 0;ii<ModuleCount;ii++){
if(tracedmodules[ii].lBase < offset && offset < tracedmodules[ii].lCodeMaxAddress){
ActualModule = tracedmodules[ii];
memcpy(&iModuleNum, ActualModule.FileName, 8);
break;
}
}

iModuleNum++;

if(InScope(offset)){
// this decides stuff.. modulenum^ is to get differen values for different modules
// we can't use the true address due to aslr
long value = (iModuleNum^(offset-ActualModule.lBase));
it = VisitedBreakPoints.find(value);
if(it==VisitedBreakPoints.end())
VisitedBreakPoints.insert(value);
}

// handle "startup"
if(HasAnalyzedEntryPoint==false){
offset = (long)I_NT.OptionalHeader.AddressOfEntryPoint;
printf("Analyzing initial code section starting at: %x\n", offset);
Analyze(offset,dwThreadId);
HasAnalyzedEntryPoint = true;
dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
GetModuleInfo();
return;
}

it = BranchingDynamicBreakPoint.find(offset);

if(it!=BranchingDynamicBreakPoint.end()){

#ifdef VERBOSE
printf("hit dyn bp %x \n", offset);
#endif

long tooffset = 0;
CONTEXT ctx;
char bytes[8];
HANDLE th = OpenThread(THREAD_ALL_ACCESS, NULL, dwThreadId);
ctx.ContextFlags = CONTEXT_FULL;
GetThreadContext(th, &ctx);

if(META_GET_FC(BranchingDynamicRegister[offset].meta) != FC_UNC_BRANCH){
Analyze(offset+BranchingDynamicRegister[offset].size, dwThreadId);
}

if(BranchingDynamicRegister[offset].ops[0].type == O_REG){
tooffset = readreg(&ctx, BranchingDynamicRegister[offset].ops[0].index);
}
else if(BranchingDynamicRegister[offset].ops[0].type == O_MEM || BranchingDynamicRegister[offset].ops[0].type==O_SMEM){

#ifdef VERBOSE
printf("index: %d\n", BranchingDynamicRegister[offset].ops[0].index);
printf("scale: %d\n", BranchingDynamicRegister[offset].scale);
printf("disp: %d\n", BranchingDynamicRegister[offset].disp);
#endif

long reg = readreg(&ctx, BranchingDynamicRegister[offset].ops[0].index);
if(BranchingDynamicRegister[offset].scale!=0)
reg = reg*BranchingDynamicRegister[offset].scale;
reg += BranchingDynamicRegister[offset].disp;


if(!ReadProcessMemory(ProcessInformation.hProcess,(LPCVOID)reg, bytes, 8, 0))
tooffset = 0;
else
memcpy(&tooffset, bytes, sizeof(tooffset));

}else if(BranchingDynamicRegister[offset].ops[0].type==O_DISP){

long regt = BranchingDynamicRegister[offset].disp;

#ifdef VERBOSE
printf("Absolute address: %x\n", regt);
#endif

if(!ReadProcessMemory(ProcessInformation.hProcess,(LPCVOID)regt, bytes, 8, 0))
tooffset = 0; // wont be handled..
else
memcpy(&tooffset, bytes, sizeof(tooffset));

}else if (BranchingDynamicRegister[offset].ops[0].type == O_PC) {
tooffset = INSTRUCTION_GET_TARGET(&BranchingDynamicRegister[offset]);
tooffset += ActualModule.lBase;
}else if (BranchingDynamicRegister[offset].flags & FLAG_RIP_RELATIVE)
tooffset = INSTRUCTION_GET_RIP_TARGET(&BranchingDynamicRegister[offset]);
else
printf("Odd type: %d\n", BranchingDynamicRegister[offset].ops[0].type);

CloseHandle(th);

if(InScope(tooffset)){

SetBreakPoint(tooffset);
dwContinueStatus = DBG_CONTINUE;
Analyze(tooffset, dwThreadId);
RemoveBreakPoint(offset, dwThreadId);
// we never rease these because they will / could be rehit with different values
// option 2: leave them.. instead of this on/off toggling
BackFlowLocation.insert(std::make_pair(tooffset,offset));
BackFlowOffset.insert(tooffset);

return;

}else // offset is not in scope
RemoveBreakPoint(offset, dwThreadId);

return;
}

if(InScope(offset)){

it = KnownBreakPoints.find(offset);
if(it==KnownBreakPoints.end()){
printf("not handled %x:/..", offset);
char b[8];
ReadProcessMemory(ProcessInformation.hProcess,(LPCVOID)offset, b, 8, 0);
dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
return;
}

it = AnalyzedBreakPoints.find(offset);
if(it==AnalyzedBreakPoints.end()){
RemoveBreakPoint(offset, dwThreadId);
Analyze(offset, dwThreadId);
AnalyzedBreakPoints.insert(offset);
dwContinueStatus = DBG_CONTINUE;
}
else // unknown.. or already handled?
{
it = KnownBreakPoints.find(offset);
if(it!=KnownBreakPoints.end()){
dwContinueStatus = DBG_CONTINUE;
RemoveBreakPoint(offset, dwThreadId);
}else{
printf("not handled??");
dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
}
}

}else {// not in scope / let os handle..

it = KnownBreakPoints.find(offset);
if(it!=KnownBreakPoints.end()){
RemoveBreakPoint(offset, dwThreadId);
AnalyzedBreakPoints.insert(offset);
dwContinueStatus = DBG_CONTINUE;
}else{
dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
printf("outside scope.. set %x\n", DBG_EXCEPTION_NOT_HANDLED);
}
}

}

DWORD RvaToOffset(IMAGE_NT_HEADERS *NT, DWORD Rva)
{
DWORD Offset = Rva, Limit;
IMAGE_SECTION_HEADER *Img;
WORD i;
Img = IMAGE_FIRST_SECTION(NT);
if (Rva < Img->PointerToRawData)
return Rva;
for (i = 0; i < NT->FileHeader.NumberOfSections; i++)
{
if (Img[i].SizeOfRawData)
Limit = Img[i].SizeOfRawData;
else
Limit = Img[i].Misc.VirtualSize;

if (Rva >= Img[i].VirtualAddress &&
Rva < (Img[i].VirtualAddress + Limit))
{
if (Img[i].PointerToRawData != 0)
{
Offset -= Img[i].VirtualAddress;
Offset += Img[i].PointerToRawData;
}
return Offset;
}
}
return NULL;
}

DWORD Rva2Offset(DWORD dwRva, PIMAGE_SECTION_HEADER dwSecRva, USHORT uNumOfSecs)
{
for (USHORT i=0; i<uNumOfSecs; i++)
{
if (dwRva >= dwSecRva->VirtualAddress)
{
if (dwRva < dwSecRva->VirtualAddress + dwSecRva->Misc.VirtualSize)
return (DWORD)(dwRva - dwSecRva->VirtualAddress + dwSecRva->PointerToRawData) ;
}
dwSecRva ++ ;
}
return (DWORD)-1 ;
}

void ProcessDebugEvent( DEBUG_EVENT *debug_event)
{
char strEventMessage[MAX_PATH];
memset(strEventMessage, NULL, sizeof(strEventMessage));

switch(debug_event->dwDebugEventCode)
{
case CREATE_PROCESS_DEBUG_EVENT:
{
I_NT.OptionalHeader.AddressOfEntryPoint += (long)debug_event->u.CreateProcessInfo.lpBaseOfImage;
I_NT.OptionalHeader.BaseOfCode = (long)debug_event->u.CreateProcessInfo.lpBaseOfImage + I_NT.OptionalHeader.BaseOfCode;

printf("Create process: %s %x\nEntrypoint: %x BaseOfCode: %x\n", GetFileNameFromHandle(debug_event->u.CreateProcessInfo.hFile), debug_event->u.CreateProcessInfo.lpBaseOfImage, I_NT.OptionalHeader.AddressOfEntryPoint, I_NT.OptionalHeader.BaseOfCode);

_ModuleInfo NewModule;
NewModule.lBase = (long)I_NT.OptionalHeader.BaseOfCode;
NewModule.lCodeMaxAddress = (long)debug_event->u.CreateProcessInfo.lpBaseOfImage+I_NT.OptionalHeader.SizeOfCode;
NewModule.lSizeOfCode = (long)I_NT.OptionalHeader.SizeOfCode;
strcpy(NewModule.FileName, GetFileNameFromHandle(debug_event->u.CreateProcessInfo.hFile));

NewModule.PCodeCache = (unsigned char*)malloc(I_NT.OptionalHeader.SizeOfCode);
NewModule.bDll = false;
unsigned long NumBytesRead;

if(!ReadProcessMemory(ProcessInformation.hProcess,(LPCVOID)I_NT.OptionalHeader.BaseOfCode, NewModule.PCodeCache, I_NT.OptionalHeader.SizeOfCode, 0))
printf("Could not read processmemory..!\n");

tracedmodules[ModuleCount] = NewModule;
ModuleCount++;
}
break;

case CREATE_THREAD_DEBUG_EVENT:
printf("Thread 0x%x (Id: %d) created at: 0x%x\n",
debug_event->u.CreateThread.hThread,
debug_event->dwThreadId,
debug_event->u.CreateThread.lpStartAddress);

AnalyzeException((long)debug_event->u.CreateThread.lpStartAddress,debug_event->dwThreadId );

break;
case EXIT_THREAD_DEBUG_EVENT:
sprintf(strEventMessage, "Thread exit \n");
break;

case EXIT_PROCESS_DEBUG_EVENT:
printf("Process exit.. 0x%x blocks %d\n", debug_event->u.ExitProcess.dwExitCode, VisitedBreakPoints.size());
bContinueDebugging = false;
break;

case LOAD_DLL_DEBUG_EVENT:
{
char filename[MAX_PATH];
sprintf(filename, GetFileNameFromHandle(debug_event->u.LoadDll.hFile));
DllNameMap.insert(std::make_pair( debug_event->u.LoadDll.lpBaseOfDll, filename));

#ifdef VERBOSE
printf("%s -> %x\n", filename, debug_event->u.LoadDll.lpBaseOfDll);
#endif

// these are hardcoded so certain programs run through ok
// Agree, could make a filter input param :> // This Dll doesn't dig..
if(strstr(filename, "WINDOWS") == NULL && strstr(filename, "System32") == NULL && strstr(filename, "Windows")==NULL && strstr(filename, "OSPPC.DLL") == NULL)
{
HANDLE file = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == INVALID_HANDLE_VALUE) {
printf("Could not open file %s (error %d)\n", filename, GetLastError());
}else{

LPVOID base;
PIMAGE_DOS_HEADER image_dos_header;
DWORD header;
HANDLE hMap = CreateFileMapping(debug_event->u.LoadDll.hFile, 0, PAGE_READONLY | SEC_COMMIT, 0, 0, 0);
if(hMap==NULL)
break;

base = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);

if(base==NULL)
break;

image_dos_header = (PIMAGE_DOS_HEADER)base;

if (image_dos_header->e_magic != IMAGE_DOS_SIGNATURE)
UnmapViewOfFile(base);
else{

IMAGE_NT_HEADERS DLLI_NT_HEADER;
header = (DWORD)base + image_dos_header->e_lfanew;
memcpy(&DLLI_NT_HEADER, (void*)header, sizeof(IMAGE_NT_HEADERS));

_ModuleInfo LoadedModule;
LoadedModule.lBase = (long)debug_event->u.LoadDll.lpBaseOfDll+DLLI_NT_HEADER.OptionalHeader.BaseOfCode;
LoadedModule.lCodeMaxAddress = (long)debug_event->u.LoadDll.lpBaseOfDll+DLLI_NT_HEADER.OptionalHeader.BaseOfCode+DLLI_NT_HEADER.OptionalHeader.SizeOfCode;
LoadedModule.lSizeOfCode = DLLI_NT_HEADER.OptionalHeader.SizeOfCode;
// put true if you don't want analyzis of the internals.
LoadedModule.bDll = false;
strcpy(LoadedModule.FileName, filename);

LoadedModule.PCodeCache = (unsigned char*)malloc(LoadedModule.lSizeOfCode);
unsigned long NumBytesRead;

if(!ReadProcessMemory(ProcessInformation.hProcess,(LPCVOID)LoadedModule.lBase, LoadedModule.PCodeCache, LoadedModule.lSizeOfCode, 0))
printf("Could not read process memory..!\n");

DWORD dwExportDirectoryVA = DLLI_NT_HEADER.OptionalHeader.DataDirectory[0].VirtualAddress;
DWORD dwExportDirectoryVS = DLLI_NT_HEADER.OptionalHeader.DataDirectory[0].Size;

PIMAGE_SECTION_HEADER pCurSection ;
if (dwExportDirectoryVS != 0)
{

PIMAGE_SECTION_HEADER pImageSectionHeader = (PIMAGE_SECTION_HEADER) ((DWORD) base + image_dos_header->e_lfanew + sizeof(IMAGE_NT_HEADERS)) ;
pCurSection = pImageSectionHeader ;
USHORT sNumOfSections = DLLI_NT_HEADER.FileHeader.NumberOfSections ;
PIMAGE_EXPORT_DIRECTORY pImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((DWORD) base + Rva2Offset(dwExportDirectoryVA, pCurSection, sNumOfSections)) ;

DWORD dwFunAddrTable ;
DWORD *vFunAddrTable ;
dwFunAddrTable = (DWORD) base + Rva2Offset(pImageExportDirectory->AddressOfFunctions, pImageSectionHeader, sNumOfSections) ;

vFunAddrTable = (DWORD *)dwFunAddrTable ;

for (DWORD j=0; j<pImageExportDirectory->NumberOfNames; j++)
{
SetBreakPoint((*vFunAddrTable)+(long)debug_event->u.LoadDll.lpBaseOfDll);
vFunAddrTable ++;
}
}
else
printf("No exports\n") ;

tracedmodules[ModuleCount] = LoadedModule;
ModuleCount++;
}
}
break;
}
}
break;

case UNLOAD_DLL_DEBUG_EVENT:
break;

case EXCEPTION_DEBUG_EVENT:
{

EXCEPTION_DEBUG_INFO& exception = debug_event->u.Exception;
#ifdef VERBOSE
printf("Exception at %x, exception-code: 0x%08x\n",
exception.ExceptionRecord.ExceptionAddress,
exception.ExceptionRecord.ExceptionCode);
#endif
switch( exception.ExceptionRecord.ExceptionCode)
{
case STATUS_BREAKPOINT:
AnalyzeException((long)exception.ExceptionRecord.ExceptionAddress,debug_event->dwThreadId );
break;
default:
AnalyzeException((long)exception.ExceptionRecord.ExceptionAddress, debug_event->dwThreadId);
}

break;
}
}

#ifdef VERBOSE
printf("Status: %s %x ",strEventMessage, dwContinueStatus);
#endif
ContinueDebugEvent(debug_event->dwProcessId, debug_event->dwThreadId, dwContinueStatus);

// Reset
dwContinueStatus = DBG_CONTINUE;
}

void WriteLog()
{
FILE *fp1;
fp1 = fopen(OutputFileName, "w");
set<long>::iterator it;
for (it = VisitedBreakPoints.begin() ; it != VisitedBreakPoints.end(); it++)
fprintf(fp1, "%x\n", *it);
fclose(fp1);

}

char* ReadFileName(char* p)
{
// parse out filename
char* tmp = strstr(p,"\\");
while(tmp!=NULL){
p = tmp+1;
tmp = strstr(p,"\\");
}
return p;
}

bool ReadFileNTHeader(char* ExecutablePath)
{
HANDLE hFile;
hFile = CreateFile(ExecutablePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
printf("Could not open file %s (error %d)\n", ExecutablePath, GetLastError());
return false;
}

LPVOID base;
PIMAGE_DOS_HEADER image_dos_header;
DWORD header;
HANDLE hMap = CreateFileMapping(hFile, 0, PAGE_READONLY | SEC_COMMIT, 0, 0, 0);
base = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);

image_dos_header = (PIMAGE_DOS_HEADER)base;

if (image_dos_header->e_magic != IMAGE_DOS_SIGNATURE)
{
printf("invalid DOS stub!\n");
UnmapViewOfFile(base);
return false;
}

header = (DWORD)base + image_dos_header->e_lfanew;
memcpy(&I_NT, (void*)header, sizeof(IMAGE_NT_HEADERS));

#ifdef VERBOSE
printf("Image NT Headers\n");
printf("Image Base: %x\n", I_NT.OptionalHeader.ImageBase);
printf("Entrypoint: %x\n", I_NT.OptionalHeader.AddressOfEntryPoint);
printf("Base: %x\n", I_NT.OptionalHeader.BaseOfCode);
printf("CodeSize: %x\n", I_NT.OptionalHeader.SizeOfCode);
#endif

return true;
}

int main(int argc, char **argv)
{
// argv handling -> :/
int argvCount = 1;
char ExecutablePath[MAX_PATH];
char Parameters[MAX_PATH];
char FileName[MAX_PATH];

ZeroMemory(ExecutablePath, MAX_PATH);
ZeroMemory(Parameters, MAX_PATH);
ZeroMemory(FileName, MAX_PATH);
ZeroMemory(OutputFileName, MAX_PATH);

if (argc != 9) {
showUsage();
return -1;
}

// ye ye this sucks, in a hurry :)
// prime sample of how not to handle arguments..
if (strcmp(argv[argvCount], "-f") == 0) {
argvCount++;
strncpy(ExecutablePath, argv[argvCount], strlen(argv[argvCount])+1);
argvCount++;
}else{
showUsage();
return -1;
}

if (strcmp(argv[argvCount], "-p") == 0) {
argvCount++;
// setting quotes around the params, you need to modify this to get more params than one passed.
strcat(Parameters, "\"");
strcat(Parameters, argv[argvCount]);
strcat(Parameters, "\"\0");
argvCount++;
}else{
showUsage();
return -1;
}

if (strcmp(argv[argvCount], "-o") == 0) {
argvCount++;
strcat(OutputFileName, argv[argvCount]);
argvCount++;
}else{
showUsage();
return -1;
}

if (strcmp(argv[argvCount], "-w") == 0) {
argvCount++;
TimeOut = atoi(argv[argvCount]);
}else{
showUsage();
return -1;
}

strcpy(FileName, ReadFileName(ExecutablePath));

EnableDebugPriv();

printf("Runtrace starting..\n");
printf("Command: %s %s\n", ExecutablePath, Parameters);

if(!ReadFileNTHeader(ExecutablePath))
return -1;

memset(&StartupInfo,0,sizeof(StartupInfo));
StartupInfo.cb= sizeof(StartupInfo);

char cmdline[MAX_PATH];
memset(&cmdline, 0, MAX_PATH);
strcat(cmdline, FileName);
strcat(cmdline, " ");
strcat(cmdline, Parameters);

if(!CreateProcess(ExecutablePath,cmdline, NULL, NULL, false, DEBUG_PROCESS, NULL,NULL,&StartupInfo,&ProcessInformation)) {
printf("Could not run the program.");
return -3;
}

CloseHandle(ProcessInformation.hThread);
DEBUG_EVENT debug_event = {0};
time_t t0 = time(NULL);
while(bContinueDebugging)
{
if (WaitForDebugEvent(&debug_event,1000))
ProcessDebugEvent(&debug_event);

time_t t1 = time(NULL);
double time_in_seconds = difftime(t1, t0);
if(time_in_seconds>TimeOut)
bContinueDebugging = false;
}

TerminateProcess(ProcessInformation.hProcess,0);
WriteLog();
printf("Done.\n");

return 0;
}





Comments

RSS Feed Subscribe to this comment feed

No comments yet, be the first!

Login or Register to post a comment

File Archive:

July 2017

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Jul 1st
    2 Files
  • 2
    Jul 2nd
    3 Files
  • 3
    Jul 3rd
    15 Files
  • 4
    Jul 4th
    4 Files
  • 5
    Jul 5th
    15 Files
  • 6
    Jul 6th
    15 Files
  • 7
    Jul 7th
    10 Files
  • 8
    Jul 8th
    2 Files
  • 9
    Jul 9th
    10 Files
  • 10
    Jul 10th
    15 Files
  • 11
    Jul 11th
    15 Files
  • 12
    Jul 12th
    19 Files
  • 13
    Jul 13th
    16 Files
  • 14
    Jul 14th
    15 Files
  • 15
    Jul 15th
    3 Files
  • 16
    Jul 16th
    2 Files
  • 17
    Jul 17th
    8 Files
  • 18
    Jul 18th
    11 Files
  • 19
    Jul 19th
    15 Files
  • 20
    Jul 20th
    15 Files
  • 21
    Jul 21st
    15 Files
  • 22
    Jul 22nd
    7 Files
  • 23
    Jul 23rd
    2 Files
  • 24
    Jul 24th
    19 Files
  • 25
    Jul 25th
    28 Files
  • 26
    Jul 26th
    2 Files
  • 27
    Jul 27th
    0 Files
  • 28
    Jul 28th
    0 Files
  • 29
    Jul 29th
    0 Files
  • 30
    Jul 30th
    0 Files
  • 31
    Jul 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2016 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close