• 标 题:在程序前加一个密码输入框的过程!
  • 作 者:cobra1111
  • 时 间:2003/08/01 09:28pm
  • 链 接:http://bbs.pediy.com

最近在家无事,尝试着修改一下软件,在程序前加一个密码输入框,输入密码正确才能进入游戏,否则退出。

程序名:暴力天使(一个小游戏),当然参考了pll621的文章,在此表示感谢!

首先,需要一个对话框资源,用ResourceHacker打开程序,发现有一个现成的对话框资源:

103 DIALOGEX 22, 17, 179, 50
style DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
EXstyle WS_EX_TOOLWINDOW
CAPTION "About"
LANGUAGE LANG_JAPANESE, 0x1
FONT 9, "MS Pゴシック"
{
  CONTROL 107, 2, STATIC, SS_ICON | WS_CHILD | WS_VISIBLE, 4, 8, 20, 20
  CONTROL "BAROQUE-SHOOTING", -1, STATIC, SS_LEFT | SS_NOPREFIX | WS_CHILD | WS_VISIBLE | WS_GROUP, 28, 8, 76, 8
  CONTROL "(C)2000 STING ALL RIGHT RESERVED", -1, STATIC, SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 52, 40, 124, 8
  CONTROL "STINGWEB", 1000, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 128, 4, 48, 28
  CONTROL "[TIMEATTACK]", -1, STATIC, SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 72, 20, 46, 8
}

去掉一些无用的标签,然后加上一个Edit控件,修改后的资源如下:

103 DIALOGEX 100, 100, 186, 70
style DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
EXstyle WS_EX_TOOLWINDOW
CAPTION "Please Input the Password"
LANGUAGE LANG_JAPANESE, 0x1
FONT 9, "MS Pゴシック"
{
  CONTROL "", 100, EDIT, ES_LEFT | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 18, 25, 94, 14
  CONTROL "确定", 1000, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 126, 26, 48, 12
  CONTROL "Please Input The Password!!", 0, STATIC, SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 17, 9, 94, 14
}

用OD打开程序,发现有两处调用DialogParamBoxA处,我就用了0040ED8E处的调用,让程序的OEP指向0040ED8E

0040ED8E   > 8B15 6C0D4700  MOV EDX,DWORD PTR DS:[470D6C]            ;  Case 68 ('h') of switch 0040ED5B
0040ED94   . 6A 00          PUSH 0                                   ; /lParam = NULL
0040ED96   . 68 40F14000    PUSH SHOOTING.0040F140                   ; |DlgProc = SHOOTING.0040F140
0040ED9B   . 57             PUSH EDI                                 ; |hOwner
0040ED9C   . 6A 67          PUSH 67                                  ; |pTemplate = 67
0040ED9E   . 52             PUSH EDX                                 ; |hInst => NULL
0040ED9F   . FF15 74914100  CALL DWORD PTR DS:[<&USER32.DialogBoxPar>; \DialogBoxParamA
0040EDA5   . E9 DB000000    JMP SHOOTING.0040EE85

通过40ED96处,我知道此窗口的消息处理程序在40F140处。(DialogParamBoxA函数产生的是模式窗口,有自己的消息处理过程。如果没有现成的DialogParamBoxA调用,可以自己模仿下面程序构建一个)

0040F140   . 8B4424 08      MOV EAX,DWORD PTR SS:[ESP+8]
0040F144   . 2D 10010000    SUB EAX,110                              ;  Switch (cases 110..111)
'''110 = WM_INITDIALOG
0040F149   . 74 52          JE SHORT SHOOTING.0040F19D
0040F14B   . 48             DEC EAX
'''111=WM_COMMAND
0040F14C   . 74 05          JE SHORT SHOOTING.0040F153
0040F14E   . 33C0           XOR EAX,EAX                              ;  Default case of switch 0040F144
0040F150   . C2 1000        RETN 10
0040F153   > 8B4424 0C      MOV EAX,DWORD PTR SS:[ESP+C]             ;  Case 111 of switch 0040F144
0040F157   . 25 FFFF0000    AND EAX,0FFFF
0040F15C   . 7E 3F          JLE SHORT SHOOTING.0040F19D
0040F15E   . 83F8 02        CMP EAX,2
0040F161   . 7E 2D          JLE SHORT SHOOTING.0040F190
0040F163   . 3D E8030000    CMP EAX,3E8'注意3E8为“确定”按钮的ID
0040F168   . 75 33          JNZ SHORT SHOOTING.0040F19D;原来按此按钮会连接到以下网站
0040F16A   . A1 98D44100    MOV EAX,DWORD PTR DS:[41D498]
0040F16F   . 6A 05          PUSH 5                                   ; /IsShown = 5
0040F171   . 6A 00          PUSH 0                                   ; |DefDir = NULL
0040F173   . 6A 00          PUSH 0                                   ; |Parameters = NULL
0040F175   . 50             PUSH EAX                                 ; |FileName => "http://www.sting.co.jp/"
0040F176   . 68 BCD04100    PUSH SHOOTING.0041D0BC                   ; |Operation = "open"
0040F17B   . FF15 BC914100  CALL DWORD PTR DS:[<&USER32.GetDesktopWi>; |[GetDesktopWindow
0040F181   . 50             PUSH EAX                                 ; |hWnd
0040F182   . FF15 38914100  CALL DWORD PTR DS:[<&SHELL32.ShellExecut>; \ShellExecuteA
0040F188   . B8 01000000    MOV EAX,1
0040F18D   . C2 1000        RETN 10
0040F190   > 8B4C24 04      MOV ECX,DWORD PTR SS:[ESP+4]
0040F194   . 6A 02          PUSH 2                                   ; /Result = 2
0040F196   . 51             PUSH ECX                                 ; |hWnd
0040F197   . FF15 5C914100  CALL DWORD PTR DS:[<&USER32.EndDialog>]  ; \EndDialog
0040F19D   > B8 01000000    MOV EAX,1                                ;  Case 110 of switch 0040F144  
0040F1A2   . C2 1000        RETN 10

我修改为:

0040F140   . 8B4424 08      MOV EAX,DWORD PTR SS:[ESP+8]
0040F144   . 2D 10010000    SUB EAX,110                              ;  Switch (cases 110..111)
0040F149   . 74 52          JE SHORT TRY_SH-M.0040F19D
0040F14B   . 48             DEC EAX
0040F14C   . 74 05          JE SHORT TRY_SH-M.0040F153
0040F14E   . 33C0           XOR EAX,EAX                              ;  Default case of switch 0040F144
0040F150   . C2 1000        RETN 10
0040F153   > 8B4424 0C      MOV EAX,DWORD PTR SS:[ESP+C]             ;  Case 111 of switch 0040F144
0040F157   . 90             NOP
0040F158   . 90             NOP
0040F159   . 90             NOP
0040F15A   . 90             NOP
0040F15B   . 90             NOP
0040F15C   . 90             NOP
0040F15D   . 90             NOP
0040F15E   . 83F8 02        CMP EAX,2
0040F161   . 7E 2D          JLE SHORT TRY_SH-M.0040F190
0040F163   . 3D E8030000    CMP EAX,3E8
0040F168   . 0F84 B29A0000  JE TRY_SH-M.00418C20;如果按钮按下,则跳到我自己的代码,见下!
0040F16E   . 3D 64000001    CMP EAX,1000064;在Edit(ID=64H)控件具有焦点时,eax=100064
0040F173   . 90             NOP;我们不做任何处理,返回。
0040F174   . 90             NOP
0040F175   . 90             NOP;中间无用代码,都nop掉
0040F176   . 90             NOP
0040F177   . 90             NOP
0040F178   . 90             NOP
0040F179   . 90             NOP
0040F17A   . 90             NOP
0040F17B   . 90             NOP
0040F17C   . 90             NOP
0040F17D   . 90             NOP
0040F17E   . 90             NOP
0040F17F   . 90             NOP
0040F180   . 90             NOP
0040F181   . 90             NOP
0040F182   . 90             NOP
0040F183   . 90             NOP
0040F184   . 90             NOP
0040F185   . 90             NOP
0040F186   . 90             NOP
0040F187   . 90             NOP
0040F188   . B8 01000000    MOV EAX,1
0040F18D   . C2 1000        RETN 10
0040F190   > 8B4C24 04      MOV ECX,DWORD PTR SS:[ESP+4]
0040F194   . 6A 02          PUSH 2                                   ; /Result = 2
0040F196   . 51             PUSH ECX                                 ; |hWnd
0040F197   . FF15 5C914100  CALL DWORD PTR DS:[<&USER32.EndDialog>]  ; \EndDialog
0040F19D   > B8 01000000    MOV EAX,1                                ;  Case 110 of switch 0040F144
0040F1A2   . C2 1000        RETN 10

0040F168跳到这里:

00418C20   > 68 70DA4100    PUSH TRY_SH-M.0041DA70                   ; /Title = "Please Input the Password"
00418C25   . 6A 00          PUSH 0                                   ; |Class = 0
00418C27   . FF15 9C914100  CALL DWORD PTR DS:[<&USER32.FindWindowA>>; \FindWindowA
00418C2D   . A3 00DD4100    MOV DWORD PTR DS:[41DD00],EAX
;找到对话框,获得句柄,放入[41DD00]

00418C32   . 6A 20          PUSH 20                                  ; /Count = 20 (32.)
00418C34   . 68 00DC4100    PUSH TRY_SH-M.0041DC00                   ; |Buffer = TRY_SH-M.0041DC00
00418C39   . 90             NOP                                      ; |
00418C3A   . 6A 64          PUSH 64                                  ; |ControlID = 64 (100.)
00418C3C   . FF35 00DD4100  PUSH DWORD PTR DS:[41DD00]               ; |hWnd = NULL
00418C42   . FF15 93505700  CALL DWORD PTR DS:[575093]               ; \GetDlgItemTextA
;调用GetDlgItemTextA,获得Edit框的内容

00418C48   . BF 00DC4100    MOV EDI,TRY_SH-M.0041DC00
00418C4D   . BE 60DA4100    MOV ESI,TRY_SH-M.0041DA60                ;  ASCII "cobra1111"
00418C52   . B9 09000000    MOV ECX,9     ;重复九次len(cobra1111)=9
00418C57   . F3:A6          REPE CMPS BYTE PTR ES:[EDI],BYTE PTR DS:>
;比较密码是否为cobra1111,如果是,则可进入游戏;否则继续比较
00418C59   .^74 95          JE SHORT TRY_SH-M.00412327      ;到程序原来的OEP

00418C5B   . BF 00DC4100    MOV EDI,TRY_SH-M.0041DC00
00418C60   . BE A0DA4100    MOV ESI,TRY_SH-M.0041DAA0                ;  ASCII "jjxme"
00418C65   . B9 05000000    MOV ECX,5
00418C6A   . F3:A6          REPE CMPS BYTE PTR ES:[EDI],BYTE PTR DS:>
00418C6C   . 74 19          JE SHORT TRY_SH-M.00418C87     ;比较是否为jjxme,如果是可进入作弊模式(呵呵)


如果都不是,则出错。
00418C6E   . 6A 00          PUSH 0                                   ; /style = MB_OK|MB_APPLMODAL
00418C70   . 68 B0DA4100    PUSH TRY_SH-M.0041DAB0                   ; |Title = "Wrong!!"
00418C75   . 68 B8DA4100    PUSH TRY_SH-M.0041DAB8                   ; |Text = "密码错误!你不能玩游戏!!"
00418C7A   . 6A 00          PUSH 0                                   ; |hOwner = NULL
00418C7C   . FF15 58914100  CALL DWORD PTR DS:[<&USER32.MessageBoxA>>; \MessageBoxA
00418C82   . 33C0           XOR EAX,EAX
00418C84   . C2 1000        RETN 10;返回消息处理

418C6C跳到这里:

00418C87   > C605 00DC4100 >MOV BYTE PTR DS:[41DC00],1;用[41DC00]为1,则进入作弊模式(时间无限)
;用游戏修改器就能找到关键点,在此不详述
00418C8E   .^E9 5DFFFFFF    JMP TRY_SH-M.00418BF0

00418C93   > 803D 00DC4100 >CMP BYTE PTR DS:[41DC00],1;如果为1,则跳过减少时间的代码
00418C9A   .^0F84 7352FFFF  JE TRY_SH-M.0040DF13
00418CA0   . 833D 48134700 >CMP DWORD PTR DS:[471348],2;不然,则回复原程序代码,没有作弊模式
00418CA7   .^0F83 5052FFFF  JNB TRY_SH-M.0040DEFD
00418CAD   . 48             DEC EAX
00418CAE   . 66:8946 2A     MOV WORD PTR DS:[ESI+2A],AX
00418CB2   .^E9 5C52FFFF    JMP TRY_SH-M.0040DF13

把以下程序修改:
0040DEF4   . 73 07          JNB SHORT SHOOTING.0040DEFD
0040DEF6   . 48             DEC EAX
0040DEF7   . 66:8946 2A     MOV WORD PTR DS:[ESI+2A],AX
修改后:
0040DEF4   . E9 9AAD0000    JMP TRY_SH-M.00418C93;跳到自己的代码,见上!
0040DEF9     90             NOP
0040DEFA     90             NOP

现在来解决对话框右上角的“x”按钮了,如果不处理的话,即使密码不正确,按了这个键也会进入游戏。
本来我想在消息处理过程中处理这个东西,后来没有成功。还好我发现了一个更简单的方法:

0040ED8E   > 8B15 6C0D4700  MOV EDX,DWORD PTR DS:[470D6C]            ;  Case 68 ('h') of switch 0040ED5B
0040ED94   . 6A 00          PUSH 0                                   ; /lParam = NULL
0040ED96   . 68 40F14000    PUSH SHOOTING.0040F140                   ; |DlgProc = SHOOTING.0040F140
0040ED9B   . 57             PUSH EDI                                 ; |hOwner
0040ED9C   . 6A 67          PUSH 67                                  ; |pTemplate = 67
0040ED9E   . 52             PUSH EDX                                 ; |hInst => NULL
0040ED9F   . FF15 74914100  CALL DWORD PTR DS:[<&USER32.DialogBoxPar>; \DialogBoxParamA
0040EDA5   . E9 DB000000    JMP SHOOTING.0040EE85;由于按了x按钮后会关闭对话框,然后就会来到这一句,我只要改这一句就行了。好,改为 JMP 00418CB7

00418CB7   > 6A 00          PUSH 0                                   ; /style = MB_OK|MB_APPLMODAL
00418CB9   . 68 80DB4100    PUSH TRY_SH-M.0041DB80                   ; |Title = "再见!"00
00418CBE   . 68 86DB4100    PUSH TRY_SH-M.0041DB86                   ; |Text = "再见! 欢迎下次再来!!"
00418CC3   . 6A 00          PUSH 0                                   ; |hOwner = NULL
00418CC5   . FF15 58914100  CALL DWORD PTR DS:[<&USER32.MessageBoxA>>; \MessageBoxA
00418CCB   .^E9 8A97FFFF    JMP TRY_SH-M.0041245A

显示一个“欢迎下次再来”的对话框后,跳到退出程序的代码(程序中现成的):

0041245A  |> 68 FF000000    PUSH 0FF                                 ; /ExitCode = FF
0041245F  \. FF15 28914100  CALL DWORD PTR DS:[<&KERNEL32.ExitProces>; \ExitProcess
00412465   . C3             RETN

OK!基本完成了!
修改过程中,DialogBoxParamA是原程序中没有的,用LoadPE导入即可。
从分利用程序中原本就有的代码!


在这里我问一个问题:
在418C93处,我原本打算用这样的方法来修改掉程序中的代码:
mov byte ptr[40DEF4],90
mov byte ptr[40DEF5],90
但是不能运行,不知为何?记得在看雪的书中有过这样的例子的!
更奇怪的是,如果我在运行这句之前,用OD随便修改一下内存中的数据,指令就能正常运行了。
望高手指教!


小弟第一次写这样的文章,思路混乱,表达不清,望诸位谅解!
谢谢!!