include windows.inc
include kernel32.inc
include user32.inc
include Comctl32.inc
include shell32.inc
includelib kernel32.lib
includelib user32.lib
includelib Comctl32.lib
includelib shell32.lib
DlgProc PROTO :HWND,:UINT,:WPARAM,PARAM
GetRegKey PROTO
.const
IDD_DLGMAIN equ 101
IDC_REGKEY equ 1003
BREAKFLAG equ 100000h
.data
szFmt db '%1X',0
szMsgErr db '本注册机必须与下面的软件放在同一目录内:',0dh ;中间不要有其它变量定义
szEXEName db '例子.exe',0 ;换成要注册的软件可执行文件名
BreakPoint dd 0401131h ;可以改成要设断点的地址
OldCode db 050h ;BreakPoint处的第一字节内容,帮我们判断壳是否操作完毕,完毕才能设断点
;RegKeyAddr dd 40305ch ;注册码在debugee中的存放地址
BreakCode db 0CCh,90h,90h,90h ;最好别改动
TimesBreak dd 0 ;最好别改动
;#########################################################################
.data?
PI PROCESS_INFORMATION<>
Buffer db 256dup(?)
************************************************************************************************************
我这个贴子只说了内存注册机的一般原理,未做成通用模板,因此需要会编程的使用者视具体情况添加或改动代码,比如多线程、多次中断在同一地址等。后面有人跟贴提到这两个问题。对于多线程问题,我想了个对策,代码见上文,调试了没问题。对于第二个问题,最好去读一下我转贴的《Win32调试API教程》之第三部分。我的大致思路是:
1.第一次正确发生int3中断时,设为单步模式,为的是后面有机会再写入断点。也可以设硬件断点,那是另一套思路了。
2.在单步事件到来时,重写入断点代码,暂不单步了
.if DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT
(前面的判断代码此处略)
mov @ThreadConText.ContextFlags, CONTEXT_CONTROL
invoke GetThreadContext, PI.hThread, addr @ThreadConText
or @ThreadConText.regFlag,100h ;设为单步模式,为的是后面有机会再写入断点
invoke WriteProcessMemory,PI.hProcess,ecx,addr @BakCode,sizeof @BakCode,NULL ;恢复debugee原来的代码
invoke SetThreadContext,PI.hThread,addr @ThreadConText ;修改debugee的EIP,让其继续运行
inc TimesBreak
(后面的代码此处略)
.elseif DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_SINGLE_STEP ;int3中断后紧接着单步一次
invoke WriteProcessMemory,PI.hProcess,BreakPoint,addr BreakCode,sizeof BreakCode,NULL ;再次写入中断代码,对付同一地址多次中断。