- #include
"stdafx.h"
#include <windows.h>
bool SetBreakpoint(PROCESS_INFORMATION &pi,
int address, unsigned char expectedByte)
{
unsigned char charBuffer;
if (!ReadProcessMemory(pi.hProcess, (void*)address,
&charBuffer, 1, NULL))
{
return false;
}
if (charBuffer!=expectedByte)
{
return false;
}
charBuffer = 0xCC;
if (!WriteProcessMemory(pi.hProcess, (void*)address,
&charBuffer, 1, NULL))
{
return false;
}
return true;
}
bool AdjustInstructionPointer(HANDLE hThread, int delta)
{
CONTEXT context;
context.ContextFlags = 0x1003F; // CONTEXT_ALL
if (!GetThreadContext(hThread,&context))
{
return false;
}
context.Eip+=delta;
if (!SetThreadContext(hThread,&context))
{
return false;
}
return true;
}
bool ClearBreakpoint(PROCESS_INFORMATION &pi,
int address, unsigned char originalByte)
{
unsigned char charBuffer;
if (!ReadProcessMemory(pi.hProcess, (void*)address,
&charBuffer, 1, NULL))
{
return false;
}
if (charBuffer!=0xCC)
{
return false;
}
charBuffer = originalByte;
if (!WriteProcessMemory(pi.hProcess, (void*)address,
&charBuffer, 1, NULL))
{
return false;
}
return AdjustInstructionPointer(pi.hThread, -1);
}
bool WaitForEventAtAddress(DEBUG_EVENT &de,int addressExpected,
DWORD &dwContinueStatus)
{
int address;
bool boolDebugging = true;
while (boolDebugging)
{
dwContinueStatus = DBG_CONTINUE;
if
(!WaitForDebugEvent(&de,INFINITE))
{
return false;
}
if (de.dwDebugEventCode ==
EXCEPTION_DEBUG_EVENT)
{
dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
address = (DWORD)de.u.Exception.ExceptionRecord.ExceptionAddress;
if
((de.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)
||
(de.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP))
{
dwContinueStatus = DBG_CONTINUE;
}
}
if (address ==
addressExpected)
{
boolDebugging = false;
}
else
ContinueDebugEvent(de.dwProcessId, de.dwThreadId, dwContinueStatus);
}
return true;
}
bool WaitForSingleStep(DEBUG_EVENT &de, DWORD &dwContinueStatus)
{
int address;
bool boolDebugging = true;
while (boolDebugging)
{
dwContinueStatus = DBG_CONTINUE;
if
(!WaitForDebugEvent(&de,INFINITE))
{
return false;
}
if (de.dwDebugEventCode ==
EXCEPTION_DEBUG_EVENT)
{
dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
address = (DWORD)de.u.Exception.ExceptionRecord.ExceptionAddress;
if
((de.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)
||
(de.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP))
{
dwContinueStatus = DBG_CONTINUE;
}
if
(de.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP)
{
return true;
}
}
ContinueDebugEvent(de.dwProcessId, de.dwThreadId, dwContinueStatus);
}
return true;
}
bool WaitForExitProcess(DEBUG_EVENT &de, DWORD
&dwContinueStatus)
{
int address;
bool boolDebugging = true;
while (boolDebugging)
{
dwContinueStatus = DBG_CONTINUE;
if
(!WaitForDebugEvent(&de,INFINITE))
{
return false;
}
if (de.dwDebugEventCode ==
EXCEPTION_DEBUG_EVENT)
{
dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
address = (DWORD)de.u.Exception.ExceptionRecord.ExceptionAddress;
if
((de.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)
||
(de.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP))
{
dwContinueStatus = DBG_CONTINUE;
}
}
else if (de.dwDebugEventCode ==
EXIT_PROCESS_DEBUG_EVENT)
return true;
ContinueDebugEvent(de.dwProcessId, de.dwThreadId, dwContinueStatus);
}
return true;
}
void DecodeException(EXCEPTION_RECORD &er,DWORD
&dwContinueStatus)
{
dwContinueStatus =
DBG_EXCEPTION_NOT_HANDLED;
switch(er.ExceptionCode)
{
case EXCEPTION_BREAKPOINT:
dwContinueStatus =
DBG_CONTINUE;
break;
case EXCEPTION_SINGLE_STEP:
dwContinueStatus =
DBG_CONTINUE;
break;
}
}
void ContinueExecution()
{
bool boolDebugging = true;
DEBUG_EVENT de;
DWORD dwContinueStatus;
while (boolDebugging)
{
dwContinueStatus
= DBG_CONTINUE;
if
(!WaitForDebugEvent(&de,INFINITE))
{
boolDebugging
= false;
return;
}
switch (de.dwDebugEventCode)
{
case EXCEPTION_DEBUG_EVENT:
DecodeException(de.u.Exception.ExceptionRecord,dwContinueStatus);
break;
default:
dwContinueStatus = DBG_CONTINUE;
}
ContinueDebugEvent(de.dwProcessId, de.dwThreadId,
dwContinueStatus);
}
}
int main(int argc, char* argv[])
{
//launch target
STARTUPINFO si;
PROCESS_INFORMATION pi;
CONTEXT context;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
if( !CreateProcess( "VideoSplitter.exe",
NULL,
NULL,
NULL,
FALSE,
NORMAL_PRIORITY_CLASS |
DEBUG_PROCESS
NULL,
NULL,
&si,
&pi )
)
{
return -1;
}
DEBUG_EVENT de;
DWORD dwContinueStatus;
DWORD address = 0;
int baseAddress;
/*
1 run until
Debug event: EXCEPTION_DEBUG_EVENT
at address:A68006
*/
if
(!WaitForEventAtAddress(de,0xA68006,dwContinueStatus))
return -1;
/*
2 bp at
00A7D8BC 8B0D 88CFA900 MOV
ECX,DWORD PTR DS:[A9CF88]
(replace 8B with CC at 00A7D8BC)
*/
baseAddress = 0x00A7D8BC;
if (!SetBreakpoint(pi, baseAddress, 0x8B))
return -1;
// 3 continue
ContinueDebugEvent(de.dwProcessId, de.dwThreadId,
dwContinueStatus);
/*
4 wait for bp
Debug event: EXCEPTION_DEBUG_EVENT
at address: 00A7D8BC
*/
if
(!WaitForEventAtAddress(de,0x00A7D8BC,dwContinueStatus))
return -1;
/*
5 clear breakpoint and do EIP = EIP - 1
(restore 8B at 00A7D8BC)
*/
baseAddress = 0x00A7D8BC;
if (!ClearBreakpoint(pi,baseAddress,0x8B))
return -1;
/*
6 bp at
00A7DAA5 74
68 JE
SHORT 00A7DB0F
(replace 74 with CC at 00A7DAA5)
*/
baseAddress = 0x00A7DAA5;
if (!SetBreakpoint(pi, baseAddress, 0x74))
return -1;
// 7 continue
ContinueDebugEvent(de.dwProcessId, de.dwThreadId,
dwContinueStatus);
/*
8 wait for bp
Debug event: EXCEPTION_DEBUG_EVENT
at address: 00A7DAA5
*/
if
(!WaitForEventAtAddress(de,0x00A7DAA5,dwContinueStatus))
return -1;
/* 9
adjust Z flag
clear breakpoint;
set breakpoint at the next instruction
:
00A7DAA7 385D
08 CMP BYTE PTR
SS:[EBP+8],BL
continue
*/
context.ContextFlags = 0x1003F; //CONTEXT_ALL;
if (!GetThreadContext(pi.hThread,&context))
{
return -1;
}
context.EFlags = context.EFlags | 0x40; // 1000000
if (!SetThreadContext(pi.hThread,&context))
{
return -1;
}
baseAddress = 0x00A7DAA5;
if (!ClearBreakpoint(pi,baseAddress,0x74))
return -1;
baseAddress = 0x00A7DB0F;
if (!SetBreakpoint(pi, baseAddress, 0x51))
return -1;
ContinueDebugEvent(de.dwProcessId, de.dwThreadId,
dwContinueStatus);
/*
10 wait for bp
Debug event: EXCEPTION_DEBUG_EVENT
at address: 00A7DB0F
*/
if
(!WaitForEventAtAddress(de,0x00A7DB0F,dwContinueStatus))
return -1;
/*
11 clear bp
set bp at
00A7DAA5 74
68 JE
SHORT 00A7DB0F
(replace 74 with CC at 00A7DAA5)
continue
*/
baseAddress = 0x00A7DB0F;
if (!ClearBreakpoint(pi,baseAddress,0x51))
return -1;
baseAddress = 0x00A7DAA5;
if (!SetBreakpoint(pi, baseAddress, 0x74))
return -1;
ContinueDebugEvent(de.dwProcessId, de.dwThreadId,
dwContinueStatus);
/*
12 wait for bp
Debug event: EXCEPTION_DEBUG_EVENT
at address: 00A7DAA5
*/
if
(!WaitForEventAtAddress(de,0x00A7DAA5,dwContinueStatus))
return -1;
/* 13
adjust Z flag
clear breakpoint;
set breakpoint at the next instruction
continue
*/
context.ContextFlags = 0x1003F; //CONTEXT_ALL;
if (!GetThreadContext(pi.hThread,&context))
{
return -1;
}
context.EFlags = context.EFlags | 0x40; // 1000000
if (!SetThreadContext(pi.hThread,&context))
{
return -1;
}
baseAddress = 0x00A7DAA5;
if (!ClearBreakpoint(pi,baseAddress,0x74))
return -1;
baseAddress = 0x00A7DB0F;
if (!SetBreakpoint(pi, baseAddress, 0x51))
return -1;
ContinueDebugEvent(de.dwProcessId, de.dwThreadId,
dwContinueStatus);
/*
14 wait for bp
Debug event: EXCEPTION_DEBUG_EVENT
at address: 00A7DB0F
*/
if
(!WaitForEventAtAddress(de,0x00A7DB0F,dwContinueStatus))
return -1;
// 15 clear
bp, continue, wait for a single step
baseAddress = 0x00A7DB0F;
if (!ClearBreakpoint(pi,baseAddress,0x51))
return -1;
ContinueDebugEvent(de.dwProcessId, de.dwThreadId,
dwContinueStatus);
WaitForSingleStep(de, dwContinueStatus);
//16 SET HDW
BRKP & continue
context.ContextFlags = 0x1003F; //CONTEXT_ALL;
if (!GetThreadContext(pi.hThread,&context))
{
return -1;
}
context.Dr0 = 0x00412049;
context.Dr7 = context.Dr7 |
0x30001;
if (!SetThreadContext(pi.hThread,&context))
{
return -1;
}
ContinueDebugEvent(de.dwProcessId, de.dwThreadId,
dwContinueStatus);
// 17 wait for
a single step, clear hdw brkp,
// set bp at 00410D2A and 00412049 & continue
WaitForSingleStep(de, dwContinueStatus);
context.ContextFlags = 0x1003F; //CONTEXT_ALL;
if (!GetThreadContext(pi.hThread,&context))
{
return -1;
}
context.Dr0 = 0;
context.Dr7 = context.Dr7 & (
~(0x30000));
if (!SetThreadContext(pi.hThread,&context))
{
return -1;
}
baseAddress = 0x00410D2A;
if (!SetBreakpoint(pi, baseAddress, 0x85))
return -1;
baseAddress = 0x00412049;
if (!SetBreakpoint(pi, baseAddress, 0x50))
return -1;
ContinueDebugEvent(de.dwProcessId, de.dwThreadId,
dwContinueStatus);
// 18 wait for
break at 0x00410D2A, clear bp, eax = 1
if
(!WaitForEventAtAddress(de,0x00410D2A,dwContinueStatus))
return -1;
baseAddress = 0x00410D2A;
if (!ClearBreakpoint(pi,baseAddress,0x85))
return -1;
context.ContextFlags = 0x1003F; //CONTEXT_ALL;
if (!GetThreadContext(pi.hThread,&context))
{
return -1;
}
context.Eax = 1;
if (!SetThreadContext(pi.hThread,&context))
{
return -1;
}
ContinueDebugEvent(de.dwProcessId, de.dwThreadId,
dwContinueStatus);
// 19 wait for
break at 0x00412049, clear bp, eax = 0x0A
if
(!WaitForEventAtAddress(de,0x00412049,dwContinueStatus))
return -1;
baseAddress = 0x00412049;
if (!ClearBreakpoint(pi,baseAddress,0x50))
return -1;
context.ContextFlags = 0x1003F; //CONTEXT_ALL;
if (!GetThreadContext(pi.hThread,&context))
{
return -1;
}
context.Eax = 0x0a;
if (!SetThreadContext(pi.hThread,&context))
{
return -1;
}
ContinueDebugEvent(de.dwProcessId, de.dwThreadId,
dwContinueStatus);
WaitForExitProcess(de, dwContinueStatus);
return 0;
}
|