7

我想开始学习逆向工程。所以我决定从简单的开始。我创建了这个简单的程序:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  printf ("Hello World!\n");
  system("PAUSE");  
  return 0;
}

我在 Ollydbg 中对它进行了伪装。所以我想尝试将 printf 更改为“World Hello”。但我不知道现在该怎么办。你能指导我,或者至少告诉我理论上应该做什么吗?

4

1 回答 1

12

在这种情况下,您需要编辑传递给 的字符串printf,但首先我们需要获取它的地址。查看调用 的代码printf,我们会看到类似这样的内容:

PUSH mymodule.1234567
CALL printf
ADD ESP,4

0x1234567因此,如果我们通过ctrl+转到地址g,我们会看到:

01234567   48 65 6C 6C 6F 20 57 6F 72 6C 64 0A 00 00 00 00  Hello World.....

所以现在您可以将该字符串编辑为您想要的任何内容,只要您不溢出可用空间并保留空终止符。

保存更改取决于您如何加载二进制文件(通过附加或只是冷查看),最简单的方法是通过冷查看(将 olly 纯粹用作反汇编程序/汇编程序)。通过view -> file右键单击并disassemble从上下文菜单中选择来访问它。在这种模式下,通过右键单击并save file从上下文菜单中选择来完成保存。

在调试器模式下(也就是附加时),保存是通过右键单击并从copy to executable上下文菜单选项中选择一个选项来完成的。


更新

如果您正在调试 GCC 生成的代码,它通常会避免生成PUSH's 并倾向于将变量直接放入堆栈中,使用MOV [ESP+c],c/r/m. 使用 GCC 编译您的示例,您会看到类似于 (for main) 的代码:

00401AFC     /$  PUSH EBP
00401AFD     |.  MOV EBP,ESP
00401AFF     |.  AND ESP,FFFFFFF0
00401B02     |.  SUB ESP,10
00401B05     |.  CALL GCCOllyT.0040182C
00401B0A     |.  MOV DWORD PTR SS:[ESP],GCCOllyT.00403024   ; ||ASCII "Hello World!"
00401B11     |.  CALL <JMP.&msvcrt.puts>                    ; |\puts
00401B16     |.  MOV DWORD PTR SS:[ESP],GCCOllyT.00403031   ; |ASCII "PAUSE"
00401B1D     |.  CALL <JMP.&msvcrt.system>                  ; \system
00401B22     |.  XOR EAX,EAX
00401B24     |.  LEAVE
00401B25     \.  RETN

重要的是要注意 GCC 将调用优化为printf调用puts. 在这种情况下,您知道要查找的字符串,您可以在调试器模式下使用 olly,右键单击并选择search for -> all referenced text strings,然后从列表中简单地选择所需的字符串以查找使用它的代码,或按照其地址找到它的.data部分条目,以便您可以更改它。找到它的更长方法是使用右键单击上下文菜单中可用的二进制搜索,但这通常是对文本字符串的浪费。

为了涵盖所有基础,假设我们需要从入口点获取代码。如果我们从模块入口点导航到代码的位置,我们将像这样遵循链:

GCCOllyT.<ModuleEntryPoint> 0> $ >PUSH EBP
0040126D                       . >MOV EBP,ESP
0040126F                       . >SUB ESP,18
00401272                       . >MOV DWORD PTR SS:[ESP],1
00401279                       . >CALL DWORD PTR DS:[<&msvcrt.__set_app_type>;  msvcrt.__set_app_type
0040127F                       . >CALL GCCOllyT.00401000
00401284                       . >PUSH EBP
00401285                       . >MOV EBP,ESP
00401287                       . >SUB ESP,18
0040128A                       . >MOV DWORD PTR SS:[ESP],2
00401291                       . >CALL DWORD PTR DS:[<&msvcrt.__set_app_type>;  msvcrt.__set_app_type
00401297                       . >CALL GCCOllyT.00401000
0040129C                       $ >PUSH EBP
0040129D                       . >MOV EBP,ESP
0040129F                       . >SUB ESP,8
004012A2                       . >MOV EAX,DWORD PTR DS:[<&msvcrt.atexit>]
004012A7                       . >LEAVE
004012A8                       . >JMP EAX

从这里我们看到唯一可行的调用为GCCOllyT.00401000,然后,我们在这里结束(这是 GCC mainCRTstartup):

00401000   /$ >PUSH EBP
00401001   |. >MOV EBP,ESP
00401003   |. >PUSH EBX
00401004   |. >SUB ESP,34
00401007   |. >MOV EAX,DWORD PTR DS:[403038]
0040100C   |. >TEST EAX,EAX
0040100E   |. >JE SHORT GCCOllyT.0040102C
00401010   |. >MOV DWORD PTR SS:[ESP+8],0
00401018   |. >MOV DWORD PTR SS:[ESP+4],2
00401020   |. >MOV DWORD PTR SS:[ESP],0
00401027   |. >CALL EAX
00401029   |. >SUB ESP,0C
0040102C   |> >MOV DWORD PTR SS:[ESP],GCCOllyT.00401110           ; |
00401033   |. >CALL <JMP.&KERNEL32.SetUnhandledExceptionFilter>   ; \SetUnhandledExceptionFilter
00401038   |. >PUSH EAX
00401039   |. >CALL GCCOllyT.004013CC
0040103E   |. >CALL GCCOllyT.004014AC
00401043   |. >MOV DWORD PTR SS:[EBP-10],0
0040104A   |. >LEA EAX,DWORD PTR SS:[EBP-10]
0040104D   |. >MOV DWORD PTR SS:[ESP+10],EAX
00401051   |. >MOV EAX,DWORD PTR DS:[402000]
00401056   |. >MOV DWORD PTR SS:[ESP+C],EAX
0040105A   |. >LEA EAX,DWORD PTR SS:[EBP-C]
0040105D   |. >MOV DWORD PTR SS:[ESP+8],EAX
00401061   |. >MOV DWORD PTR SS:[ESP+4],GCCOllyT.00404004
00401069   |. >MOV DWORD PTR SS:[ESP],GCCOllyT.00404000
00401070   |. >CALL <JMP.&msvcrt.__getmainargs>
00401075   |. >MOV EAX,DWORD PTR DS:[404018]
0040107A   |. >TEST EAX,EAX
0040107C   |. >JNZ SHORT GCCOllyT.004010C8
0040107E   |> >CALL <JMP.&msvcrt.__p__fmode>
00401083   |. >MOV EDX,DWORD PTR DS:[402004]
00401089   |. >MOV DWORD PTR DS:[EAX],EDX
0040108B   |. >CALL GCCOllyT.004015E4
00401090   |. >AND ESP,FFFFFFF0
00401093   |. >CALL GCCOllyT.0040182C
00401098   |. >CALL <JMP.&msvcrt.__p__environ>
0040109D   |. >MOV EAX,DWORD PTR DS:[EAX]
0040109F   |. >MOV DWORD PTR SS:[ESP+8],EAX
004010A3   |. >MOV EAX,DWORD PTR DS:[404004]
004010A8   |. >MOV DWORD PTR SS:[ESP+4],EAX
004010AC   |. >MOV EAX,DWORD PTR DS:[404000]
004010B1   |. >MOV DWORD PTR SS:[ESP],EAX
004010B4   |. >CALL GCCOllyT.00401AFC
004010B9   |. >MOV EBX,EAX                                        ; |
004010BB   |. >CALL <JMP.&msvcrt._cexit>                          ; |[msvcrt._cexit
004010C0   |. >MOV DWORD PTR SS:[ESP],EBX                         ; |
004010C3   |. >CALL <JMP.&KERNEL32.ExitProcess>                   ; \ExitProcess
004010C8   |> >MOV DWORD PTR DS:[402004],EAX                      ; |||
004010CD   |. >MOV DWORD PTR SS:[ESP+4],EAX                       ; |||
004010D1   |. >MOV EBX,DWORD PTR DS:[<&msvcrt._iob>]              ; |||msvcrt._iob
004010D7   |. >MOV EAX,DWORD PTR DS:[EBX+10]                      ; |||
004010DA   |. >MOV DWORD PTR SS:[ESP],EAX                         ; |||
004010DD   |. >CALL <JMP.&msvcrt._setmode>                        ; ||\_setmode
004010E2   |. >MOV EAX,DWORD PTR DS:[404018]                      ; ||
004010E7   |. >MOV DWORD PTR SS:[ESP+4],EAX                       ; ||
004010EB   |. >MOV EAX,DWORD PTR DS:[EBX+30]                      ; ||
004010EE   |. >MOV DWORD PTR SS:[ESP],EAX                         ; ||
004010F1   |. >CALL <JMP.&msvcrt._setmode>                        ; |\_setmode
004010F6   |. >MOV EAX,DWORD PTR DS:[404018]                      ; |
004010FB   |. >MOV DWORD PTR SS:[ESP+4],EAX                       ; |
004010FF   |. >MOV EAX,DWORD PTR DS:[EBX+50]                      ; |
00401102   |. >MOV DWORD PTR SS:[ESP],EAX                         ; |
00401105   |. >CALL <JMP.&msvcrt._setmode>                        ; \_setmode
0040110A   \.^>JMP GCCOllyT.0040107E

现在我们知道调用的签名main需要 3 个参数,我们也知道它将在应用程序清理和退出之前GCCOllyT.00401AFC被调用,因此我们得到. 如您所见,启用符号需要付出高昂的代价,这可以从调试选项菜单的反汇编部分完成。

于 2011-12-30T01:23:36.830 回答