dianziguan 发表于 2013-7-14 16:04

【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

逍遥枷锁 发表于 2013-7-14 16:46

完了,高难度的来了,我发抖了,呵呵,向老师学习。

dianziguan 发表于 2013-7-14 16:49

本帖最后由 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:03

本帖最后由 不会用鼠标的人 于 2013-7-14 17:20 编辑

这个试试手。。

把原来的CALL和跳转结合成了一个jmp eax,实在是太牛B了,小弟实在是。。。。
以后破解难咯。。。

No.16 发表于 2013-7-14 17:03

前排留个名,学习了

i668899 发表于 2013-7-14 17:18

这个支持呀!破解和反破解是共存的。

xcxcxcxc 发表于 2013-7-14 17:19

qq5546680 发表于 2013-7-14 17:27

004010EB   /75 28         jnz short dzg01.00401115

candc2 发表于 2013-7-14 17:35

丶夜猫 发表于 2013-7-14 17:56

    错误地址改正确地址就哦了。。。

页: [1] 2 3
查看完整版本: 【D01E01】电子管 反破解教程之一 【让简单爆破失效】