记得n年前,我还不懂事的时候,研究游戏帐户找回工具,那时常被游戏的基址搞得。。。气血不调、大便干燥、日不能食、夜不得寐。。。那时就幻想要是我能读取寄存器就好了。当时不知道有Debug API这个东西。早上好好看了点资料,自己摸索了下,有点心得,与同学们分享下。网上有关DEBUG API的资料不是很多有个英文版的和一个翻译版的。同学们可以搜索下(key :win32 debug api),看看更详细的介绍。
debuggee被测试程序(Test.exe)很简单,明码比较的代码如下:
procedure Ttest.Button1Click(Sender: TObject);
begin
if Edit1.Text='ade123' then
MessageBox(0,'密码正确','恭喜',48)
else
MessageBox(0,'密码错误','提示',48)
end;
用OD载入得到关键算法如下:(怎么找关键算法?我也不是太懂,我也是菜鸟,凭经验+运气找到的。呵呵)
004501C3 E8 54F2FDFF CALL message.0042F41C
004501C8 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
004501CB BA 28024500 MOV EDX,message.00450228 ; ASCII "ade123"
004501D0 E8 4740FBFF CALL message.0040421C
004501D5 75 15 JNZ SHORT message.004501EC
004501D7 6A 30 PUSH 30
004501D9 68 30024500 PUSH message.00450230
004501DE 68 38024500 PUSH message.00450238
004501E3 6A 00 PUSH 0
004501E5 E8 AE62FBFF CALL <JMP.&user32.MessageBoxA>
004501EA EB 13 JMP SHORT message.004501FF
004501EC 6A 30 PUSH 30
004501EE 68 44024500 PUSH message.00450244
004501F3 68 4C024500 PUSH message.0045024C
004501F8 6A 00 PUSH 0
004501FA E8 9962FBFF CALL <JMP.&user32.MessageBoxA>
004501FF 33C0 XOR EAX,EAX
注意红色那行,将密码所在地址传递给EDX,继续一个CALL进行比较。而如果,我们在004501D0这里将程序断点断下来,然后我们去看看EDX的值,这个值就是存放的密码的地址啊。奸笑中,哈哈。
实现代码如下:
begin
wHandle:=FindWindow('TTest',0); //Tdebugee
//Sleep(5000);
//p.X:=10;
//p.Y:=10;
//wHandle:=WindowFromPoint(p);
if wHandle>0 then ade_ThreadId:=GetWindowThreadProcessId(wHandle,@ade_ProcessId);
if ade_ThreadId>0 then ade_Process:=OpenProcess(PROCESS_ALL_ACCESS,False,ade_ProcessId);
ade_Thread:=OpenThread(ade_ThreadId,False);
if DebugActiveProcess(ade_ProcessId)then
begin
//============DebugStart===============
while True do
begin
if WaitForDebugEvent(DebugEv,INFINITE) then
begin
//dwContinuesStatus:=DBG_EXCEPTION_NOT_HANDLED;
case DebugEv.dwDebugEventCode of
EXCEPTION_DEBUG_EVENT: //意外处理,断点等时触发。
begin
if (DebugEv.Exception.ExceptionRecord.ExceptionCode<>EXCEPTION_BREAKPOINT) then
rc:=False //目标程序自己异常,让它自己处理
else
begin //处理断点
if DebugEv.Exception.ExceptionRecord.ExceptionAddress=Pointer(ade_address) then
begin
SuspendThread(ThreadHandle);
rc:=True;
Context.ContextFlags:=CONTEXT_FULL;
GetThreadContext(ThreadHandle,Context);
//ReadProcessMemory(ade_Process,Pointer(Context.Edx),@adr,4,num);
//MessageBox(0,'tishi',PChar(IntToStr(Context.Edx)),48);
EAX:=Trim(GetMem(ade_Process,Context.Edx,20));
MessageBox(0,'断点事件产生',PChar(eax),48);
ResumeThread(ThreadHandle);
end;
end;
//Break;
end;
CREATE_PROCESS_DEBUG_EVENT: //刚创建调试时触发
begin
ThreadHandle:=DebugEv.CreateProcessInfo.hThread;//线程
ade_buf[0]:=$cc;
ade_buf[1]:=$90;
SuspendThread(ade_Thread); //挂起
WriteProcessMemory(ade_Process,Pointer(ade_Address),@ade_buf,2,WriteMemory); //向messagebox写入断点
ResumeThread(ade_Thread); //恢复
MessageBox(0,'Start Debug,写入完毕','Title',48);
//Break;
end;
EXIT_PROCESS_DEBUG_EVENT: //退出调试时触发
begin
MessageBox(0,'End Debug','Title',48);
//Break;
end;
end;//end case
if rc then
ContinueDebugEvent(DebugEv.dwProcessId,DebugEv.dwThreadId,DBG_CONTINUE)//本程序处理
else
ContinueDebugEvent(DebugEv.dwProcessId,DebugEv.dwThreadId,DBG_EXCEPTION_NOT_HANDLED); //目标程序自己处理
end;
end;
end
else
MessageBox(0,'调试目标进程出错','Title',48);
end;
运行效果如下:
代码没有进行修改,尽管能正确截取,但是破坏了原程序的运行,需要把CC改回,并将EIP减一。
请高手帮忙把中间delphi的代码改成c语言。