(reversing)return 到 c 中的指定位置,程序集

(reversing)return to specified location in c , assembly

我想修改下面的c代码和汇编代码只弹出一个消息框。 现在弹出'failed'消息框然后弹出'success'消息框但我想知道"Func"函数后只弹出'success'消息框的方法叫做。

我得到一个提示,答案与"RET(assembly)"有关,我不知道如何修改汇编代码和c代码。 RET 是前一个函数的 return 地址,不是吗?那么如何在代码的任一侧更改此值?

我知道 RET 是在调用 Func 函数之前保存的,所以我该怎么做???请有人帮助我!

#include <windows.h>
#include <stdio.h>

void Func(int n1, char ch) {
    int sum;
    sum = n1 + ch;
}

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShow) {

    Func(10, 'A'); 

    MessageBox(0, "Failed", "", 0);
    MessageBox(0, "Success", "", 0);
    return 0;
}

编译了 c 代码,在 ollydbg 中看起来像这样。

// Func 
00401000  /$  55            PUSH EBP
00401001  |.  8BEC          MOV EBP,ESP
00401003  |.  51            PUSH ECX
00401004  |.  0FBE45 0C     MOVSX EAX,BYTE PTR SS:[EBP+C]
00401008  |.  8B4D 08       MOV ECX,DWORD PTR SS:[EBP+8]
0040100B  |.  03C8          ADD ECX,EAX
0040100D  |.  894D FC       MOV DWORD PTR SS:[EBP-4],ECX
00401010  |.  8BE5          MOV ESP,EBP
00401012  |.  5D            POP EBP
00401013  \.  C3            RETN

// WinMain
00401014  /$  55            PUSH EBP
00401015  |.  8BEC          MOV EBP,ESP
00401017  |.  6A 41         PUSH 41                                  ; /Arg2 = 00000041
00401019  |.  6A 0A         PUSH 0A                                  ; |Arg1 = 0000000A
0040101B  |.  E8 E0FFFFFF   CALL test.00401000                       ; \test.00401000
00401020  |.  83C4 08       ADD ESP,8
00401023  |.  6A 00         PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL
00401025  |.  68 A0544000   PUSH test.004054A0                       ; |Title = ""
0040102A  |.  68 30504000   PUSH test.00405030                       ; |Text = "Failed"
0040102F  |.  6A 00         PUSH 0                                   ; |hOwner = NULL
00401031  |.  FF15 94404000 CALL DWORD PTR DS:[<&USER32.MessageBoxA>>; \MessageBoxA
00401037  |.  6A 00         PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL
00401039  |.  68 A4544000   PUSH test.004054A4                       ; |Title = ""
0040103E  |.  68 38504000   PUSH test.00405038                       ; |Text = "Success"
00401043  |.  6A 00         PUSH 0                                   ; |hOwner = NULL
00401045  |.  FF15 94404000 CALL DWORD PTR DS:[<&USER32.MessageBoxA>>; \MessageBoxA
0040104B  |.  33C0          XOR EAX,EAX
0040104D  |.  5D            POP EBP
0040104E  \.  C2 1000       RETN 10

这些 __stdcall、__cdecl、__fastcall 函数是否与此问题相关? 或者也许是 RETN 论点?

如果我理解正确你的问题 - 你需要修改你的 C 代码来使一个 MessageBox 调用消失,而不是从源代码中删除一个调用。最简单的方法是修改函数 return 地址以直接跳转到第二个 MessageBox。让我们用一个简单的例子来说明这种方法。

#include <stdio.h>

void test(){}

int main(void)
{
    test();

    printf("%s\n", "test1");
    printf("%s\n", "test2");

    return(0);
}

main 函数的反汇编(相关):

来自 test 函数的

Return 地址将是 011B17F3。如果我们想跳过第一个 printf 调用,我们希望它是 011B1805。所以它必须增加 0x12.

为此,我们必须从堆栈中检索保存的 return 地址,增加它,然后将其写回。

void test()
{
    __asm
    {
        mov eax, [ebp+4]
        add eax, 0x12
        mov [ebp+4], eax
    }
}