逆向基础3. 结构体数组的汇编结构

结构体数组的汇编结构

在栈上的数组数据结构

测试使用结构体如下

1
2
3
4
5
6
typedef struct {
int id;
int count;
int count2;
int count3;
} GameObject;

测试代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int main()
{
GameObject objs[3] = {
GameObject{1, 0x12, 0x23, 0x34},
GameObject{2, 0x45, 0x56, 0x67},
GameObject{3, 0x78, 0x89, 0x90}
};

auto obj1 = &objs[0];
auto obj2 = &objs[1];
auto obj3 = &objs[2];


auto count1 = obj1->count;
auto count2 = obj2->count2;
auto count3 = obj3->count3;

auto sum = count1 + count2 + count3;

return 0;
}

生成汇编如下:

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
sub    rsp, 0x90                ; 分配栈空间
lea rdi, [rsp + 0x20] ; 数组开始地址为 rsp + 0x20

; 填充内存为0xcccccccc
mov ecx, 0x1c
mov eax, 0xcccccccc
rep stosd dword ptr es:[rdi], eax

; 填充初始化数据
mov dword ptr [rsp + 0x28], 0x1
mov dword ptr [rsp + 0x2c], 0x12
mov dword ptr [rsp + 0x30], 0x23
mov dword ptr [rsp + 0x34], 0x34
mov dword ptr [rsp + 0x38], 0x2
mov dword ptr [rsp + 0x3c], 0x45
mov dword ptr [rsp + 0x40], 0x56
mov dword ptr [rsp + 0x44], 0x67
mov dword ptr [rsp + 0x48], 0x3
mov dword ptr [rsp + 0x4c], 0x78
mov dword ptr [rsp + 0x50], 0x89
mov dword ptr [rsp + 0x54], 0x90

; [rsp + 0x68] = &objs[0]
mov eax, 0x10
imul rax, rax, 0x0
lea rax, [rsp + rax + 0x28]
mov qword ptr [rsp + 0x68], rax

; [rsp + 0x70] = &objs[1]
mov eax, 0x10
imul rax, rax, 0x1
lea rax, [rsp + rax + 0x28]
mov qword ptr [rsp + 0x70], rax

; [rsp + 0x78] = &objs[2]
mov eax, 0x10
imul rax, rax, 0x2
lea rax, [rsp + rax + 0x28]
mov qword ptr [rsp + 0x78], rax

; [rsp + 0x80] = objs[0].count
mov rax, qword ptr [rsp + 0x68]
mov eax, dword ptr [rax + 0x4]
mov dword ptr [rsp + 0x80], eax

; [rsp + 0x84] = objs[1].count2
mov rax, qword ptr [rsp + 0x70]
mov eax, dword ptr [rax + 0x8]
mov dword ptr [rsp + 0x84], eax

; [rsp + 0x88] = objs[2].count3
mov rax, qword ptr [rsp + 0x78]
mov eax, dword ptr [rax + 0xc]
mov dword ptr [rsp + 0x88], eax

; sum = count1 + count2 + count3
mov eax, dword ptr [rsp + 0x84]
mov ecx, dword ptr [rsp + 0x80]
add ecx, eax
mov eax, ecx
add eax, dword ptr [rsp + 0x88]
mov dword ptr [rsp + 0x8c], eax

...

可以看出其栈如下

rsp偏移类型内容

0x28

dword

objs[0].id

1

0x2c

dword

objs[0].count

0x12

0x30

dword

objs[0].count2

0x23

0x34

dword

objs[0].count3

0x34

0x38

dword

objs[1].id

2

0x3c

dword

objs[1].count

0x45

0x40

dword

objs[1].count2

0x56

0x44

dword

objs[1].count3

0x67

0x48

dword

objs[2].id

3

0x4c

dword

objs[2].count

0x78

0x50

dword

objs[2].count2

0x89

0x54

dword

objs[2].count3

0x90

0x68

qword

&objs[0]

rsp + 0x28

0x70

qword

&objs[1]

rsp + 0x38

0x78

qword

&objs[2]

rsp + 0x48

0x80

dword

objs[0].count

0x84

dword

objs[1].count2

0x88

dword

objs[2].count3

0x8c

dword

sum

其取值的方式为
[&arr + sizeof(obj) * offset + member_offset]

在堆上的数组取值方式

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
GameObject **createObjArr()
{
auto **objs = new GameObject *[3];
objs[0] = new GameObject{1, 0x12, 0x23, 0x34};
objs[1] = new GameObject{2, 0x45, 0x56, 0x67};
objs[2] = new GameObject{3, 0x78, 0x89, 0x90};
return objs;
}


int main()
{
auto objs = createObjArr();

int count1 = objs[0]->count;
int count2 = objs[1]->count2;
int count3 = objs[2]->count3;

int sum = count1 + count2 + count3;

return 0;
}
Warning
此处忽略内存回收, 忽略分析创建, 仅仅研究如何取值

生成汇编如下:

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
; [rsp + 0x20] = &arr
mov qword ptr [rsp + 0x20], rax


mov eax, 0x8
imul rax, rax, 0x0
mov rcx, qword ptr [rsp + 0x20]
mov rax, qword ptr [rcx + rax]
mov eax, dword ptr [rax + 0x4]
mov dword ptr [rsp + 0x28], eax

mov eax, 0x8 ; eax = sizeof(GameObject *)
imul rax, rax, 0x1 ; rax = sizeof(GameObject *) * 1
mov rcx, qword ptr [rsp + 0x20]
mov rax, qword ptr [rcx + rax] ; rax = &arr + eax
mov eax, dword ptr [rax + 0x8] ; eax = [rax + 0x8]
mov dword ptr [rsp + 0x2c], eax ; [rsp + 0x2c] = eax


mov eax, 0x8
imul rax, rax, 0x2
mov rcx, qword ptr [rsp + 0x20]
mov rax, qword ptr [rcx + rax]
mov eax, dword ptr [rax + 0xc]
mov dword ptr [rsp + 0x30], eax

mov eax, dword ptr [rsp + 0x2c]
mov ecx, dword ptr [rsp + 0x28]
add ecx, eax
mov eax, ecx
add eax, dword ptr [rsp + 0x30]
mov dword ptr [rsp + 0x34], eax

对于堆上的数组, 取值为
[[&arr + sizeof(obj*) * offset] + member_offset]


逆向基础3. 结构体数组的汇编结构
https://simonkimi.githubio.io/2024/07/29/逆向基础3-结构体数组的汇编结构/
作者
simonkimi
发布于
2024年7月29日
许可协议