IDA,很好很强大

本文详细对比了使用不同编译器(MinGW与VS2010)编译同一C++代码段后,通过IDA Pro进行反编译的结果差异。主要关注了函数与变量命名的变化,以及反编译效率与可读性的提升。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


IDA,这款可以把程序反编译成C语言的东西。。

我用我们老师C++课上留的一道小学奥赛水平的弱智题的程序代码为例,先用MinGW编译,结果用IDA反编译出了几千个函数,全都是sub_加编号的名称,每一个都很短,变量名都是v1、v2等等的,一点也看不懂,我甚至连主函数在哪里都找不到。

然后又用VS2010编译,再反编译,令我大开眼界,函数名、变量名全能被正确地反编译出来,主程序反编译得也非常漂亮(那道题我就写了一个主函数)。

给大家展示下,

源程序的主函数:

int main(void){
    now = tail = 0;
    stk[0] = "http://www.acm.org/";
    while ((cin >> in)&&(in[0] != 'Q')){
        if (in[0] == 'V')    {
            now += 1;

            cin >> stk[now];
            cout << stk[now] << endl;

            tail = now;
        };

        if (in[0] == 'B')   {
            if (now == 0){
                cout << "Ignored" << endl;
            }else{
                -- now;
                cout << stk[now] << endl;
            };
        };

        if (in[0] == 'F')   {
            if (now == tail){
                cout << "Ignored" << endl;
            }else{
                ++ now;
                cout << stk[now] << endl;
            };
        };
    };

    return 0;
};

用VS2010编译,然后反编译出的主函数:

int __cdecl main()
{
int v0; // eax@1
int *v1; // eax@2
int *v2; // eax@5
char v3; // zf@7
int v4; // eax@7
int v5; // eax@8
int *v6; // ecx@9
int v7; // eax@13
int *v8; // ecx@16
int v9; // eax@20
int v10; // eax@23
void *v12; // [sp-4h] [bp-Ch]@20

tail = 0;
now = 0;
std__basic_string_char_std__char_traits_char__std__allocator_char_____assign();
v0 = std__operator___char_std__char_traits_char__std__allocator_char____0(std__cin);
if ( (*(_DWORD *)(*(_DWORD *)(*(_DWORD *)v0 + 4) + v0 + 12) & 6) == 0 ? v0 + *(_DWORD *)(*(_DWORD *)v0 + 4) : 0 )
{
    do
    {
      v1 = (int *)in;
      if ( (unsigned int)dword_405098 < 0x10 )
        v1 = &in;
      if ( *(_BYTE *)v1 == 81 )
        break;
      v2 = (int *)in;
      if ( (unsigned int)dword_405098 < 0x10 )
        v2 = &in;
      v3 = *(_BYTE *)v2 == 86;
      v4 = now;
      if ( v3 )
      {
        ++now;
        std__operator___char_std__char_traits_char__std__allocator_char____0(std__cin);
        v5 = std__operator___char_std__char_traits_char__std__allocator_char_(std__cout, &stk + 7 * now);
        std__basic_ostream_char_std__char_traits_char____operator__(v5, std__endl);
        v4 = now;
        tail = now;
      }
      v6 = (int *)in;
      if ( (unsigned int)dword_405098 < 0x10 )
        v6 = &in;
      if ( *(_BYTE *)v6 == 66 )
      {
        if ( v4 )
        {
          now = v4 - 1;
          v7 = std__operator___char_std__char_traits_char__std__allocator_char_(std__cout, &stk + 7 * now);
        }
        else
        {
          v7 = std__operator___std__char_traits_char_(std__cout);
        }
        std__basic_ostream_char_std__char_traits_char____operator__(v7, std__endl);
        v4 = now;
      }
      v8 = (int *)in;
      if ( (unsigned int)dword_405098 < 0x10 )
        v8 = &in;
      if ( *(_BYTE *)v8 == 70 )
      {
        if ( v4 == tail )
        {
          v12 = std__endl;
          v9 = std__operator___std__char_traits_char_(std__cout);
        }
        else
        {
          v12 = std__endl;
          now = v4 + 1;
          v9 = std__operator___char_std__char_traits_char__std__allocator_char_(std__cout, &stk + 7 * now);
        }
        std__basic_ostream_char_std__char_traits_char____operator__(v9, v12);
      }
      v10 = std__operator___char_std__char_traits_char__std__allocator_char____0(std__cin);
    }
    while ( (*(_DWORD *)(*(_DWORD *)(*(_DWORD *)v10 + 4) + v10 + 12) & 6) == 0 ? v10 + *(_DWORD *)(*(_DWORD *)v10 + 4) : 0 );
}
return 0;
}

可以看出多出了很多临时变量,那些多数是寄存器变量,此外把C++的代码全部反编译成了C的代码。。

另外,刚刚找到了MinGW编译出的主函数,反编译完的不太一样,可以和VS的对比一下:

int __cdecl sub_4015D0()
{
int v0; // eax@2
int v2; // eax@4
char v3; // dl@6
int v4; // eax@17
int v5; // ebx@17
int v6; // esi@17
int v7; // eax@17
char v8; // al@19
int v9; // eax@20
int v10; // eax@22
int v11; // ebx@22
char v12; // al@24
int v13; // eax@25
int v14; // eax@26
int v15; // ebx@26
int v16; // esi@26
int v17; // eax@26
char v18; // al@28
int v19; // eax@29
int v20; // eax@30
int v21; // ebx@30
int v22; // esi@30
int v23; // eax@30
char v24; // al@32
int v25; // eax@33
int v26; // eax@38
int v27; // ebx@38
char v28; // al@40
int v29; // eax@41

sub_413960();
dword_4741B8 = 0;
dword_4741BC = 0;
sub_449910(dword_474020, "http://www.acm.org/", 19);
while ( 1 )
{
    v0 = sub_40566C(&dword_4741E0, &dword_4741B4);
    if ( *(_BYTE *)(v0 + *(_DWORD *)(*(_DWORD *)v0 - 12) + 20) & 5 )
      return 0;
    v2 = dword_4741B4;
    if ( *(_DWORD *)(dword_4741B4 - 4) >= 0 )
    {
      sub_448C58(&dword_4741B4);
      v2 = dword_4741B4;
    }
    v3 = *(_BYTE *)v2;
    if ( *(_BYTE *)v2 == 81 )
      return 0;
    if ( *(_DWORD *)(v2 - 4) >= 0 )
    {
      sub_448C58(&dword_4741B4);
      v2 = dword_4741B4;
      v3 = *(_BYTE *)dword_4741B4;
    }
    if ( v3 == 86 )
    {
      ++dword_4741BC;
      sub_40566C(&dword_4741E0, 4 * dword_4741BC + 4669472);
      v23 = sub_466D2C(&dword_474280, dword_474020[dword_4741BC], *(_DWORD *)(dword_474020[dword_4741BC] - 12));
      v21 = v23;
      v20 = *(_DWORD *)(*(_DWORD *)v23 - 12);
      v22 = *(_DWORD *)(v21 + v20 + 124);
      if ( !v22 )
        goto LABEL_43;
      if ( *(_BYTE *)(v22 + 28) )
      {
        v24 = *(_BYTE *)(v22 + 39);
      }
      else
      {
        sub_40623C(*(_DWORD *)(v21 + v20 + 124));
        v24 = (*(int (__cdecl **)(int, signed int))(*(_DWORD *)v22 + 24))(v22, 10);
      }
      v25 = sub_4464E0(v21, v24);
      sub_4466CC(v25);
      dword_4741B8 = dword_4741BC;
      v2 = dword_4741B4;
    }
    if ( *(_DWORD *)(v2 - 4) >= 0 )
    {
      sub_448C58(&dword_4741B4);
      v2 = dword_4741B4;
    }
    if ( *(_BYTE *)v2 == 66 )
    {
      if ( dword_4741BC )
      {
        --dword_4741BC;
        v17 = sub_466D2C(&dword_474280, dword_474020[dword_4741BC], *(_DWORD *)(dword_474020[dword_4741BC] - 12));
        v15 = v17;
        v14 = *(_DWORD *)(*(_DWORD *)v17 - 12);
        v16 = *(_DWORD *)(v15 + v14 + 124);
        if ( !v16 )
          goto LABEL_43;
        if ( *(_BYTE *)(v16 + 28) )
        {
          v18 = *(_BYTE *)(v16 + 39);
        }
        else
        {
          sub_40623C(*(_DWORD *)(v15 + v14 + 124));
          v18 = (*(int (__cdecl **)(int, signed int))(*(_DWORD *)v16 + 24))(v16, 10);
        }
        v19 = sub_4464E0(v15, v18);
        sub_4466CC(v19);
        v2 = dword_4741B4;
      }
      else
      {
        sub_466D2C(&dword_474280, "Ignored", 7);
        v10 = *(_DWORD *)(dword_474280 - 12);
        v11 = *(int *)((char *)&dword_4742FC + v10);
        if ( !v11 )
          goto LABEL_43;
        if ( *(_BYTE *)(v11 + 28) )
        {
          v12 = *(_BYTE *)(v11 + 39);
        }
        else
        {
          sub_40623C(*(int *)((char *)&dword_4742FC + v10));
          v12 = (*(int (__cdecl **)(int, signed int))(*(_DWORD *)v11 + 24))(v11, 10);
        }
        v13 = sub_4464E0(&dword_474280, v12);
        sub_4466CC(v13);
        v2 = dword_4741B4;
      }
    }
    if ( *(_DWORD *)(v2 - 4) >= 0 )
    {
      sub_448C58(&dword_4741B4);
      v2 = dword_4741B4;
    }
    if ( *(_BYTE *)v2 == 70 )
    {
      if ( dword_4741BC == dword_4741B8 )
      {
        sub_466D2C(&dword_474280, "Ignored", 7);
        v26 = *(_DWORD *)(dword_474280 - 12);
        v27 = *(int *)((char *)&dword_4742FC + v26);
        if ( !v27 )
LABEL_43:
          sub_406800();
        if ( *(_BYTE *)(v27 + 28) )
        {
          v28 = *(_BYTE *)(v27 + 39);
        }
        else
        {
          sub_40623C(*(int *)((char *)&dword_4742FC + v26));
          v28 = (*(int (__cdecl **)(int, signed int))(*(_DWORD *)v27 + 24))(v27, 10);
        }
        v29 = sub_4464E0(&dword_474280, v28);
        sub_4466CC(v29);
      }
      else
      {
        ++dword_4741BC;
        v7 = sub_466D2C(&dword_474280, dword_474020[dword_4741BC], *(_DWORD *)(dword_474020[dword_4741BC] - 12));
        v5 = v7;
        v4 = *(_DWORD *)(*(_DWORD *)v7 - 12);
        v6 = *(_DWORD *)(v5 + v4 + 124);
        if ( !v6 )
          goto LABEL_43;
        if ( *(_BYTE *)(v6 + 28) )
        {
          v8 = *(_BYTE *)(v6 + 39);
        }
        else
        {
          sub_40623C(*(_DWORD *)(v5 + v4 + 124));
          v8 = (*(int (__cdecl **)(int, signed int))(*(_DWORD *)v6 + 24))(v6, 10);
        }
        v9 = sub_4464E0(v5, v8);
        sub_4466CC(v9);
      }
    }
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值