使用反汇编窗口和寄存器在内存中定位局部变量的概念?

逆向工程 拆卸 C
2021-07-03 17:23:27

我试图了解如何在内存中定位局部变量。我已经反汇编了ac代码,我有指令的地址。我想要存储该变量的内存位置。我试图在 c 代码中访问 i 的指令地址,但变量不在那里。我认为它位于与基指针的“偏移”处。但我不知道偏移的概念。任何帮助将不胜感激。

代码:

int main()
{
    int i = 10;
    int j = -1;
    int k = 4;
    int l = 9;
    int m;

    m = (i-j) + (k-l);
}

反汇编代码

int main()
{
003E13A0  push        ebp  
003E13A1  mov         ebp,esp  
003E13A3  sub         esp,0FCh  
003E13A9  push        ebx  
003E13AA  push        esi  
003E13AB  push        edi  
003E13AC  lea         edi,[ebp-0FCh]  
003E13B2  mov         ecx,3Fh  
003E13B7  mov         eax,0CCCCCCCCh  
003E13BC  rep stos    dword ptr es:[edi]  
    int i = 10;
003E13BE  mov         dword ptr [i],0Ah  
    int j = -1;
003E13C5  mov         dword ptr [j],0FFFFFFFFh  
    int k = 4;
003E13CC  mov         dword ptr [k],4  
    int l = 9;
003E13D3  mov         dword ptr [l],9  
    int m;

    m = (i-j) + (k-l);
003E13DA  mov         eax,dword ptr [i]  
003E13DD  sub         eax,dword ptr [j]  
003E13E0  mov         ecx,dword ptr [k]  
003E13E3  sub         ecx,dword ptr [l]  
003E13E6  add         eax,ecx  
003E13E8  mov         dword ptr [m],eax  
}
003E13EB  xor         eax,eax  
003E13ED  pop         edi  
003E13EE  pop         esi  
003E13EF  pop         ebx  
003E13F0  mov         esp,ebp  
003E13F2  pop         ebp  
003E13F3  ret

寄存器

EAX = 001A9478 EBX = 7EFDE000 ECX = 001A8868 EDX = 00000001 ESI = 00000000 EDI = 00000000 EIP = 00BE13A0 ESP = 003BF990 EBP = 003BF9DC EFL = 00000214 
3个回答

我不确定为什么这个问题被否决了。我将从一般的角度来回答它,因为它可能与 RE 小组的主题无关。

无论如何,您需要花一些时间了解您的处理器架构的汇编指令格式通过查看上面的反汇编,您可以获得所需的信息,但您将 (1) 需要了解每条指令的格式,并且 (2) 需要一个调试器。调试器与处理器一起工作以提取有关寄存器集的运行时信息。除了了解汇编指令格式之外,您还需要查看处理器寄存器。您需要设置断点(请参阅调试器说明)并经常检查程序计数器。

如果您尝试添加 C 指令来读取内存值,您将更改整个程序集偏移量!换句话说,通过添加指令,您可以更改值的位置。

一条有用的信息:在使用 C(和其他语言)时,通常有几条指令用于设置堆栈和传递给函数的参数。一旦你理解了每条指令是什么,你就会开始看到模式的出现。

您还可以在代码中放入一些已知指令,以帮助您进行跟踪。例如,也许做一些 printfs 并看看它们是什么样子。或者添加指令以将 0xBE 添加到 0xAD 并在生成的代码中查找这些值。

虽然您可以使用 gdb 的“disassemble main”命令完成类似的结果,但我选择编写您的示例(稍作改动),使用 mingw(无标志/选项)编译它并使用 IDA Pro 的试用版反汇编它:

.text:00401334 ; =============== S U B R O U T I N E =======================================
.text:00401334
.text:00401334 ; Attributes: bp-based frame
.text:00401334
.text:00401334 ; void main()
.text:00401334                 public _main
.text:00401334 _main           proc near               ; CODE XREF: ___mingw_CRTStartup+F8p
.text:00401334
.text:00401334 var_4           = dword ptr -4
.text:00401334
.text:00401334                 push    ebp
.text:00401335                 mov     ebp, esp
.text:00401337                 push    ebx
.text:00401338                 and     esp, 0FFFFFFF0h ; Logical AND
.text:0040133B                 sub     esp, 20h        ; Integer Subtraction
.text:0040133E                 call    ___main         ; Call Procedure
.text:00401343                 mov     dword ptr [esp+1Ch], 0Ah
.text:0040134B                 mov     dword ptr [esp+18h], 0FFFFFFFFh
.text:00401353                 mov     dword ptr [esp+14h], 4
.text:0040135B                 mov     dword ptr [esp+10h], 9
.text:00401363                 mov     eax, [esp+18h]
.text:00401367                 mov     edx, [esp+1Ch]
.text:0040136B                 mov     ecx, edx
.text:0040136D                 sub     ecx, eax        ; Integer Subtraction
.text:0040136F                 mov     eax, [esp+10h]
.text:00401373                 mov     edx, [esp+14h]
.text:00401377                 mov     ebx, edx
.text:00401379                 sub     ebx, eax        ; Integer Subtraction
.text:0040137B                 mov     eax, ebx
.text:0040137D                 add     eax, ecx        ; Add
.text:0040137F                 mov     [esp+0Ch], eax
.text:00401383                 mov     ebx, [ebp+var_4]
.text:00401386                 leave                   ; High Level Procedure Exit
.text:00401387                 retn                    ; Return Near from Procedure
.text:00401387 _main           endp

理解偏移量的关键是它完全基于程序的基地址,根据您的平台可能会有所不同。理解基地址是一个处理器、语言和操作系统特定的问题。对于 Windows 二进制文件,请对 PE 标头进行一些谷歌搜索。(这将解释 .text。)一般来说,偏移量的意思是“从程序/函数调用的开头开始多少字节”。约定认为“int”(在 C 语言中)是 4 个字节(32b),这就是为什么您通常会看到像您这样的变量彼此相距 4B。注意变量声明的偏移量:

.text:00401343 mov dword ptr [esp+1Ch], 0Ah .text:0040134B mov dword ptr [esp+18h], 0FFFFFFFFh .text:00401353 mov dword ptr [esp+14h], 05bmov.4btr. esp+10h], 9

每个变量彼此相差 4B。你有没有得到关于偏移量的提示?

偏移量与“esp”有很大关系,传统上是“堆栈指针”。

所以当你看到这一行时:

.text:00401343                 mov     dword ptr [esp+1Ch], 0Ah

您正在查看与“esp”相距“1Ch”的地址处的数据。(熟悉 HEX 算法。谷歌。)

您看到的“.text”告诉您程序的“.text”部分中特定偏移处的指令是什么。(再次使用 Google 的 PE 标头。)

我知道我还没有完全回答你的问题,但如果你在做二进制分析,你真的需要习惯大范围的歧义......逆向工程不像在高级语言中编程全部。没有数据类型的概念,只有通过查看周围指令推断出的数据类型。它的丑陋,同时它的美丽。

[编辑]

我这样改变了你的程序:

void main()
{
    int i = 10;
    int j = -1;
    int k = 4;
    int l = 9;
    int m;

    m = (i-j) + (k-l);

}

如果你用 "int main(){..}" 开始一个 C 程序,你真的必须至少有 return 0;。

由于您没有那个,我修改了程序以返回无效。

在您发布的代码中,所有变量i,j,k,l,m都是local变量

它们都将位于基指针下方的地址,即从 [ebp-4] 开始

use .cpp instead of c and make use of some advanatges of c++ in a c program like 
not having to make declaration of variables at the start 

如果您需要在自己的程序中访问它们,您可以使用以下
打印的帮助代码

all the registers  5 dwords above base pointer namely arguments to the    
function and 5 dwords below the base pointer namely Locals   

这是一个naked函数,因此它使用调用它函数的 ebp 在您的情况下由 main 构造的 ebp

#include <stdio.h>

    char regs_5args_and_5locs[] = 
    { 
        "==========Registers===================\n"
        "eax = %08x\n"
        "ebx = %08x\n"
        "ecx = %08x\n"
        "edx = %08x\n"
        "esi = %08x\n"
        "edi = %08x\n"
        "esp = %08x\n"
        "ebp = %08x\n"
        "==========Arguments===================\n"
        "1rg = %08x\n"
        "2rg = %08x\n"
        "3rg = %08x\n"
        "4rg = %08x\n"
        "5rg = %08x\n"
        "==========Locals===================\n"
        "1lo = %08x\n"
        "2lo = %08x\n"
        "3lo = %08x\n"
        "4lo = %08x\n"
        "5lo = %08x\n"
        "===================================\n"
    };
 __declspec (naked) void regsargsnlocs(void)
{
    __asm
    {
        pushad
            pushfd
            push [ebp-0x14]
        push [ebp-0x10]
        push [ebp-0x0c]
        push [ebp-0x08]
        push [ebp-0x04] 
        push [ebp+0x14]
        push [ebp+0x10] 
        push [ebp+0x0c]
        push [ebp+0x08]
        push [ebp+0x04]
        push ebp
            push esp
            push edi
            push esi
            push edx
            push ecx
            push ebx
            push eax
            lea eax, regs_5args_and_5locs
            push eax        
            call printf
            add esp,0x4c
            popfd
            popad
            retn
    }   
}


void main()
{
    regsargsnlocs();    
    int i = 10;
    int j = -1;
    int k = 4;
    int l = 9;
    int m;
    regsargsnlocs();
    m = (i-j) + (k-l);
   regsargsnlocs();
}

结果如下您可以分别注意到 i= 0xa ,j= -0x1,k= 0x4,l=0x9 ,m = 0x6 在第 2 次和第 3 次调用的局部变量中

\locvar>locvar.exe
==========Registers===================
eax = 000339e8
ebx = 7ffd4000
ecx = 00000001
edx = 0041dcf0
esi = 00000000
edi = 2d6648b4
esp = 0013ff10
ebp = 0013ff78
==========Arguments===================
1rg = 004013ca
2rg = 00000001
3rg = 000339c8
4rg = 000339e8
5rg = 4b9239ba
==========Locals===================
the locals have not been assigned yet we printed prior to them 
notice this is a cpp program not c which wont allow you a function 
before declaration of variables
1lo = 004039a1 
2lo = 00402d5b 
3lo = 0013ff80 
4lo = 004039a1
5lo = 004086a8
===================================
==========Registers===================
eax = 000339e8
ebx = 7ffd4000
ecx = 00000001
edx = 0041dcf0
esi = 00000000
edi = 2d6648b4
esp = 0013ff10
ebp = 0013ff78
==========Arguments===================
1rg = 004013ca
2rg = 00000001
3rg = 000339c8
4rg = 000339e8
5rg = 4b9239ba
==========Locals===================
1lo = 0000000a   i
2lo = 00000004   k
3lo = 00000009   l
4lo = 004039a1    m not calculated yet
5lo = ffffffff   j
===================================
==========Registers===================
eax = 00000006
ebx = 7ffd4000
ecx = fffffffb
edx = 0041dcf0
esi = 00000000
edi = 2d6648b4
esp = 0013ff10
ebp = 0013ff78
==========Arguments===================
1rg = 004013ca
2rg = 00000001
3rg = 000339c8
4rg = 000339e8
5rg = 4b9239ba
==========Locals===================
1lo = 0000000a
2lo = 00000004
3lo = 00000009
4lo = 00000006   m calculated here 3rd invocation
5lo = ffffffff
===================================