【D01E01】电子管 反破解教程之一 【让简单爆破失效】
本帖最后由 dianziguan 于 2013-7-22 09:21 编辑看了Shark恒老师的破解教程,收获颇丰。破解和反破解是矛盾的两个方面,两者是共同发展的。有矛就有盾,本文就是针对Shark恒破解教程的第一篇来的,希望学汇编的朋友能够喜欢。
Shark恒【S01E01】的原理,就是根据“登录失败”字符串,找到关键跳转,修改它,密码无论正确还是错误,都显示正确的结果。
一般注册程序,都明着判断,然后跳转。这是个软肋,能不能不这样呢?把判断过程和跳转过程都藏起来。
先提供一个小程序让大家破,是用masm32写的。
程序的关键代码在这里:
mov eax ,offset ok_1 ;;显示注册成功
mov ok1,eax
mov eax,offset err_1;显示注册不成功
mov err1,eax
invoke GetDlgItemText,hWnd,IDC_EDIT3,ADDR regbuffer1,512;获取对话框中的文本
push esi
mov esi,offset regbuffer1 ;缓冲区
cld
lodsd
sub eax,30303030h
push eax
pop edx
lodsd
sub eax,30303030h
add eax,edx
sub eax,08080808h ;计算
pushfd
pop eax ;标志寄存器的内容放到eax中
and eax,40h ;取Z位,若相等,这位为1,若不等这位为零
shr eax,4 ;如果注册码正确,这里eax==4,若注册码不正确,这里eax==0
mov edx,offset err1;指向注册不成功
add eax,edx ;注册不成功的地址+4就是注册成功
mov eax, ;如果注册码正确,这里eax==ok_1,若注册码不正确,这里eax==err_1
jmp eax ;用上面这几条指令代替了cmpjz
为方便汇编爱好者交流,程序的完整源代码贴上。
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\advapi32.inc
includelib \masm32\lib\advapi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \MASM32\LIB\oleaut32.lib
include \MASM32\include\oleaut32.inc
DlgProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
;BOOL GetVolumeInformation(
; LPCTSTRlpRootPathName, // address of root directory of the file system
; LPTSTRlpVolumeNameBuffer, // address of name of the volume
; DWORDnVolumeNameSize, // length of lpVolumeNameBuffer
; LPDWORDlpVolumeSerialNumber, // address of volume serial number
; LPDWORDlpMaximumComponentLength, // address of system's maximum filename length
; LPDWORDlpFileSystemFlags, // address of file system flags
; LPTSTRlpFileSystemNameBuffer, // address of name of file system
; DWORDnFileSystemNameSize// length of lpFileSystemNameBuffer
;);
.data
DlgName db "MyDialog",0
AppName db "注册程序,(C)电子管 2012.07.15",0
SerialNumber1 db "12345678",0
regNumber1 dd 0,0
mesberr_1 db "注册不成功",0
mesbok_1 db "注册成功",0
mesbok_2 db "注册请与本程序作者联系",20h dup(0)
.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
regbuffer1 db 512 dup(?)
err1 dd ?
ok1 dd ?
.const
IDC_EDIT2 equ 3800
IDC_EDIT3 equ 3801
IDC_BUTTON equ 3001
IDC_EXIT equ 3002
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke DialogBoxParam, hInstance, ADDR DlgName,NULL,addr DlgProc,NULL
invoke ExitProcess,eax
DlgProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_INITDIALOG
invoke SetDlgItemText,hWnd,IDC_EDIT2,ADDR SerialNumber1
.ELSEIF uMsg== WM_CLOSE
invoke EndDialog, hWnd,NULL
.ELSEIF uMsg==WM_COMMAND
mov edx,wParam
mov eax,edx
shr edx,16
.if dx==BN_CLICKED
.IF ax==IDC_BUTTON
mov eax ,offset ok_1
mov ok1,eax
mov eax,offset err_1
mov err1,eax
invoke GetDlgItemText,hWnd,IDC_EDIT3,ADDR regbuffer1,512
push esi
mov esi,offset regbuffer1
cld
lodsd
sub eax,30303030h
push eax
pop edx
lodsd
sub eax,30303030h
add eax,edx
sub eax,08080808h
pushfd
pop eax
and eax,40h
shr eax,4
mov edx,offset err1
add eax,edx
mov eax,
jmp eax
err_1:
err_2:
pop esi
invoke MessageBox,NULL,ADDR mesberr_1,ADDR AppName,MB_OK
exit_1:invoke EndDialog, hWnd,NULL
invoke ExitProcess,eax
ok_1:
pop esi
invoke MessageBox,NULL,ADDR mesbok_1,ADDR AppName,MB_OK
jmp exit_1
.ELSEIF ax==IDC_EXIT
invoke EndDialog, hWnd,NULL
.ENDIF
.ENDIF
.ELSE
mov eax,FALSE
ret
.ENDIF
mov eax,TRUE
ret
DlgProc endp
end start
完了,高难度的来了,我发抖了,呵呵,向老师学习。 本帖最后由 dianziguan 于 2013-7-18 07:06 编辑
逍遥枷锁 发表于 2013-7-14 16:46 http://www.52pojie.cn/static/image/common/back.gif
完了,高难度的来了,我发抖了,呵呵,向老师学习。
难度不高,只针对 cmpje 这样的指令进行了修改,不用比较和跳转
int WriteMe(void *addr, int wb)
{
HANDLE h=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_WRITE,
true, GetCurrentProcessId());
return WriteProcessMemory(h, addr, &wb, 1, NULL);
}
int main(int argc, char* argv[])
{
_asm {
push 0x74 ; JMP --> > JZ
push offset Here
call WriteMe
add esp, 8
Here: JMP short here
}
printf("Holy Sh^& OsIX, it worked! #JMP SHORT $-2 was changed to JZ $-2n");
return 0;
}
例程5:产生一个序列号,并在堆栈运行.
MyFunc:
push esi ; Saving the esi register on the stack
mov esi, ; ESI = &username
push ebx ; Saving other registers on the stack
push ecx
push edx
xor eax, eax ; Zeroing working registers
xor edx, edx
RepeatString: ; Byte-by-byte string-processing loop
lodsb ; Reading the next byte into AL
test al, al ; Has the end of the string been reached?
jz short Exit
; The value of the counter that processes 1 byte of the string
; must be choosen so that all bits are intermixed, but parity
; (oddness) is provided for the result of transformations
; performed by the XOR operation.
mov ecx, 21h
RepeatChar:
xor edx, eax ; Repeatedly replacing XOR with ADC
ror eax, 3
rol edx, 5
call $+5 ; EBX = EIP
pop ebx ; /
xor byte ptr , 26h;
; This instruction provides for the loop.
; The XOR instruction is replaced with ADC.
loop RepeatChar
jmp short RepeatString
Exit:
xchg eax, edx ; The result of work (ser.num) in EAX
pop edx ; Restoring the registers
pop ecx
pop ebx
pop esi
retn ; Returning from the function
本帖最后由 不会用鼠标的人 于 2013-7-14 17:20 编辑
这个试试手。。
把原来的CALL和跳转结合成了一个jmp eax,实在是太牛B了,小弟实在是。。。。
以后破解难咯。。。 前排留个名,学习了 这个支持呀!破解和反破解是共存的。 004010EB /75 28 jnz short dzg01.00401115
错误地址改正确地址就哦了。。。