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

结构体数组的汇编结构

在栈上的数组数据结构

测试使用结构体如下

cpp
typedef struct {
    int id;
    int count;
    int count2;
    int count3;
} GameObject;

测试代码如下

cpp
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;
}

生成汇编如下:

asm
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]

在堆上的数组取值方式

代码:

cpp
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
此处忽略内存回收, 忽略分析创建, 仅仅研究如何取值

生成汇编如下:

asm
; [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日
许可协议