首页
社区
课程
招聘
[原创]IDA反编译C++程序F5伪代码修复心得
发表于: 2024-6-16 23:59 5613

[原创]IDA反编译C++程序F5伪代码修复心得

2024-6-16 23:59
5613

学习参考:Reversing C++ programs with IDA pro and Hex-rays

话不多说,看效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
bool __fastcall cocos2d::LuaStack::setCai(cocos2d::LuaStack *this, const char *a2, const char *a3, const char *a4)
{
  _BOOL8 result; // x0
  size_t v8; // w26
  size_t v9; // w24
  size_t v10; // w22
  void *v11; // x0
  void *v12; // x0
  void *v13; // x0
 
  (*(void (__fastcall **)(cocos2d::LuaStack *))(*(_QWORD *)this + 240LL))(this);
  result = a4 != 0LL;
  if ( a3 != 0LL && result && a2 )
  {
    v8 = strlen(a2);
    v9 = strlen(a3);
    v10 = strlen(a4);
    v11 = malloc(v8);
    *((_QWORD *)this + 6) = v11;
    memcpy(v11, a2, v8);
    *((_DWORD *)this + 14) = v8;
    v12 = malloc(v9);
    *((_QWORD *)this + 8) = v12;
    memcpy(v12, a3, v9);
    *((_DWORD *)this + 18) = v9;
    v13 = malloc(v10);
    *((_QWORD *)this + 10) = v13;
    memcpy(v13, a4, v10);
    *((_DWORD *)this + 22) = v10;
    result = 1LL;
    *((_BYTE *)this + 44) = 1;
  }
  else
  {
    *((_BYTE *)this + 44) = 0;
  }
  return result;
}

修复后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
bool __fastcall cocos2d::LuaStack::setCai(
        cocos2d::LuaStack *this,
        const char *xxteaKey,
        const char *xxteaSign,
        const char *xorKey)
{
  _BOOL8 result; // x0
  size_t v8; // w26
  size_t v9; // w24
  size_t v10; // w22
  char *v11; // x0
  char *v12; // x0
  char *v13; // x0
 
  this->cleanupXXTEAKeyAndSign(this);
  result = xorKey != 0LL;
  if ( xxteaSign != 0LL && result && xxteaKey )
  {
    v8 = strlen(xxteaKey);
    v9 = strlen(xxteaSign);
    v10 = strlen(xorKey);
    v11 = (char *)malloc(v8);
    this->_xxteaKey = v11;
    memcpy(v11, xxteaKey, v8);
    this->_xxteaKeyLen = v8;
    v12 = (char *)malloc(v9);
    this->_xxteaSign = v12;
    memcpy(v12, xxteaSign, v9);
    this->_xxteaSignLen = v9;
    v13 = (char *)malloc(v10);
    this->_xorKey = v13;
    memcpy(v13, xorKey, v10);
    this->_xorKeyLen = v10;
    result = 1LL;
    this->_xxteaEnabled = 1;
  }
  else
  {
    this->_xxteaEnabled = 0;
  }
  return result;
}

开始之前,让我们先做套小学二年级自测题(此处非游戏代码,仅用于回忆知识):

考试环境:Debian GNU/Linux 12 (bookworm),g++ (Debian 12.2.0-14) 12.2.0,x86_64。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
using namespace std;
 
struct Base
{
    Base(int a, long b) : m_a(a), m_b(b) {}
    int m_a;
    virtual void print() { cout << "m_a = " << m_a << ", m_b = " << m_b << endl; }
    long m_b;
    virtual ~Base() { cout << "~Base() called" << endl; }
};
 
struct Derived : public Base
{
    Derived(int a, long b, int c) : Base(a, b), m_c(c) {}
    virtual ~Derived() { cout << "~Derived() called" << endl; }
    void print() { cout << "m_a = " << m_a << ", m_b = " << m_b << ", m_c = " << m_c << endl; }
    int m_c;
};
 
int main()
{
    Derived d(1, 2, 3);
    Base *pb = &d;
    cout << sizeof(d) << endl;
    cout << *(int *)((long *)pb + 3) << endl;
    void (Base::*func)() = &Base::print;
    (pb->*func)();
    ((void (*)())*(long *)*(long *)&d)();
    pb = new Derived(4, 5, 6);
    cout << (*(long *)&d == *(long *)pb) << endl;
    delete pb;
    cout << "---- 楚河汉界 ----" << endl;
}

问题是:请给出输出结果。
做完了吗,揭晓答案:

1
2
3
4
5
6
7
8
9
10
32
3
m_a = 1, m_b = 2, m_c = 3
m_a = 0, m_b = 0, m_c = 0
1
~Derived() called
~Base() called
---- 楚河汉界 ----
~Derived() called
~Base() called

如果您都做对了,那您可以直接跳到下个章节了,否则,您需要恶补以下知识点:

  • 内存对齐
  • 类对象的大小(内存布局)
  • 虚函数表指针
  • 虚函数表

限于篇幅,这里就不展开写了。
对本文而言,核心就是要弄懂如何通过指针访问数据成员及调用虚函数。


Q

通过上一章的回顾,您可能已经自信满满了,但是先别高兴太早,您和编译器的理解方式未必就是 IDA 的理解方式。
让我们处理下前面的测试题,保存成一个头文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct Base
{
    Base(int a, long b);
    int m_a;
    virtual void print();
    long m_b;
    virtual ~Base();
};
 
struct Derived : public Base
{
    Derived(int a, long b, int c);
    virtual ~Derived();
    void print();
    int m_c;
};

导入IDA中,然后插入Base_vtblDerived_vtbl两张虚函数表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 Base_vtbl       struc ; (sizeof=0x18, align=0x8, copyof_110)
00000000 print           dq ?                    ; offset
00000008 Base_dtor_8     dq ?                    ; offset
00000010 Base_dtor_10    dq ?                    ; offset
00000018 Base_vtbl       ends
00000018
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 Derived_vtbl    struc ; (sizeof=0x18, align=0x8, copyof_111)
00000000 print           dq ?                    ; offset
00000008 Derived_dtor_8  dq ?                    ; offset
00000010 Derived_dtor_10 dq ?                    ; offset
00000018 Derived_vtbl    ends
00000018

注意看虚函数表的大小,是不是比预想的多了一个四字?
不难发现,虚析构函数指针多了一个。查验可知,虚析构函数确实都多了一个:

所以,我们在构造虚函数表的时候,一定要留意虚析构函数指针,必须构造两个。


有空再写~~


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2024-8-23 15:08 被zjphoenix编辑 ,原因:
收藏
免费 3
支持
分享
最新回复 (7)
雪    币: 711
活跃值: (2453)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
新世纪IDA战士
2024-6-17 09:13
1
雪    币: 1480
活跃值: (1610)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
恶补的知识点需要在那里领?
2024-6-17 09:47
0
雪    币: 3762
活跃值: (4137)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
留个脚印,慢慢看。
2024-6-17 12:53
0
雪    币: 98
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
mark
2024-6-20 10:58
0
雪    币: 329
活跃值: (332)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
新世纪IDA战士
2024-6-27 10:40
0
雪    币: 303
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
7
大佬,有点看不懂?这个破是我们直接操作之前的代码吗?
2024-7-7 17:14
0
雪    币: 1426
活跃值: (3152)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
感谢分享
2024-7-31 10:23
0
游客
登录 | 注册 方可回帖
返回
//