分类 标签 存档 黑客派 订阅 搜索

逆向学习笔记(2)- 这是代码还是数据

101 浏览

以下的 ide 为 CodeBlocks,编译器采用的 GCC,系统为 win10 64bit, 在不同编译器和环境下汇编代码可能不同

现象

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

int getmin(int a, int b)
{
    if(a>b)
        return b;
    else
        return a;
}

typedef int (*pfunction)(int, int);

int main()
{
    int a=456789,b=123789,c=0;
    pfunction pGetmin = (pfunction)getmin;

    c = pGetmin(a, b);
    printf("%d",c);
    return 0;
}

上面这段代码是比大小输出小的,typedef int (*pfunction)(int, int);定义了一个函数指针,但是下面这段代码和上面的功能是完全一样的

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

typedef int (*pfunction)(int, int);

int main()
{
    int a=456789,b=123789,c=0;
    unsigned char loc[] =
    {
        0x55, 0x89, 0xE5, 0x8B, 0x45, 0x08, 0x3B, 0x45, 0x0C, 0x7E, 0x05, 0x8B, 0x45, 0x0C, 0xEB, 0x03, 0x8B, 0x45, 0x08, 0x5D, 0xC3
    };

    pfunction getmin = (pfunction)&loc;
    c = getmin(a, b);
    printf("%d",c);
    return 0;
}

原因分析

c = pGetmin(a, b);调用 pGetmin 的时候,在汇编中是先 call 跳到一个地址然后从那个地址再 jmp 到函数入口地址然后开始执行函数
getmin 函数整体汇编为

push   ebp
mov    ebp,esp
mov    eax,DWORD PTR [ebp+0x8]
cmp    eax,DWORD PTR [ebp+0xc]
jle    <getmin+16>
mov    eax,DWORD PTR [ebp+0xc]
jmp    <getmin+19>
mov    eax,DWORD PTR [ebp+0x8]
pop    ebp
ret

通过一些调试程序(发现 CodeBlocks 带的汇编调试没有 vc6 好用,看不到硬编码)可以得出这段汇编代码在硬编码中的值为

0x55, 0x89, 0xE5, 0x8B, 0x45, 0x08, 0x3B, 0x45, 0x0C, 0x7E, 0x05, 0x8B, 0x45, 0x0C, 0xEB, 0x03, 0x8B, 0x45, 0x08, 0x5D, 0xC3

这段数据我们在第二个代码中把它存入了一个 char 类型的数组,它虽然在数据区,但是它还是可以看作可运行的一段函数代码,我们依旧定义一个函数指针指向这个 char 类型数组的入口地址,达到了和第一种相同的效果
在编程中,我们是把代码和数据分得很开的,但是在逆向和汇编中,这个区别就不明显了,在计算机中都是以数据形式存在的,你可以说它是一串数据,也可以说它是代码

转载请注明出处

评论  
留下你的脚步
推荐阅读