调用汇编代码符号
前言
这里遇到了一个相关的CTF习题,看到其WP中的思路不错,特别学习一下
题目
其是picoCTF的asm4,题目要求获取调用asm4("picoCTF_a3112")
的结果,其中附件代码如下所示
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
58asm4:
<+0>: push ebp
<+1>: mov ebp,esp
<+3>: push ebx
<+4>: sub esp,0x10
<+7>: mov DWORD PTR [ebp-0x10],0x246
<+14>: mov DWORD PTR [ebp-0xc],0x0
<+21>: jmp 0x518 <asm4+27>
<+23>: add DWORD PTR [ebp-0xc],0x1
<+27>: mov edx,DWORD PTR [ebp-0xc]
<+30>: mov eax,DWORD PTR [ebp+0x8]
<+33>: add eax,edx
<+35>: movzx eax,BYTE PTR [eax]
<+38>: test al,al
<+40>: jne 0x514 <asm4+23>
<+42>: mov DWORD PTR [ebp-0x8],0x1
<+49>: jmp 0x587 <asm4+138>
<+51>: mov edx,DWORD PTR [ebp-0x8]
<+54>: mov eax,DWORD PTR [ebp+0x8]
<+57>: add eax,edx
<+59>: movzx eax,BYTE PTR [eax]
<+62>: movsx edx,al
<+65>: mov eax,DWORD PTR [ebp-0x8]
<+68>: lea ecx,[eax-0x1]
<+71>: mov eax,DWORD PTR [ebp+0x8]
<+74>: add eax,ecx
<+76>: movzx eax,BYTE PTR [eax]
<+79>: movsx eax,al
<+82>: sub edx,eax
<+84>: mov eax,edx
<+86>: mov edx,eax
<+88>: mov eax,DWORD PTR [ebp-0x10]
<+91>: lea ebx,[edx+eax*1]
<+94>: mov eax,DWORD PTR [ebp-0x8]
<+97>: lea edx,[eax+0x1]
<+100>: mov eax,DWORD PTR [ebp+0x8]
<+103>: add eax,edx
<+105>: movzx eax,BYTE PTR [eax]
<+108>: movsx edx,al
<+111>: mov ecx,DWORD PTR [ebp-0x8]
<+114>: mov eax,DWORD PTR [ebp+0x8]
<+117>: add eax,ecx
<+119>: movzx eax,BYTE PTR [eax]
<+122>: movsx eax,al
<+125>: sub edx,eax
<+127>: mov eax,edx
<+129>: add eax,ebx
<+131>: mov DWORD PTR [ebp-0x10],eax
<+134>: add DWORD PTR [ebp-0x8],0x1
<+138>: mov eax,DWORD PTR [ebp-0xc]
<+141>: sub eax,0x1
<+144>: cmp DWORD PTR [ebp-0x8],eax
<+147>: jl 0x530 <asm4+51>
<+149>: mov eax,DWORD PTR [ebp-0x10]
<+152>: add esp,0x10
<+155>: pop ebx
<+156>: pop ebp
<+157>: ret
解题说明
可以看到,要理清这五十多行的汇编代码,还是比较麻烦的。因此理想的方法是直接执行asm4("picoCTF_a3112")
因此一个合理的思路就是在C语言中直接进行符号调用即可
调用函数
这个很简单,就是在C中调用该导出符号即可,如下所示
1
2
3
4
5
6
7
8
extern int asm4(char *str);
int main(void) {
printf("0x%x\n", asm4("picoCTF_a3112"));
return 0;
}
汇编代码修改
这明显是通过objdump
反汇编出来的汇编代码,并且还附带这诸多的标记信息。
我们首先需要将其转换为符合格式的汇编代码,即执行如下几个步骤
- 去除代码字节序数
- 去除跳转注解
- 添加跳转标签,统一为asm4_字节序数
修改跳转地址为相对应的跳转标签
最后整理完成的汇编代码如下所示
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
62asm4:
push ebp
mov ebp,esp
push ebx
sub esp,0x10
mov DWORD PTR [ebp-0x10],0x246
mov DWORD PTR [ebp-0xc],0x0
jmp asm4_27
asm4_23:
add DWORD PTR [ebp-0xc],0x1
asm4_27:
mov edx,DWORD PTR [ebp-0xc]
mov eax,DWORD PTR [ebp+0x8]
add eax,edx
movzx eax,BYTE PTR [eax]
test al,al
jne asm4_23
mov DWORD PTR [ebp-0x8],0x1
jmp asm4_138
asm4_51:
mov edx,DWORD PTR [ebp-0x8]
mov eax,DWORD PTR [ebp+0x8]
add eax,edx
movzx eax,BYTE PTR [eax]
movsx edx,al
mov eax,DWORD PTR [ebp-0x8]
lea ecx,[eax-0x1]
mov eax,DWORD PTR [ebp+0x8]
add eax,ecx
movzx eax,BYTE PTR [eax]
movsx eax,al
sub edx,eax
mov eax,edx
mov edx,eax
mov eax,DWORD PTR [ebp-0x10]
lea ebx,[edx+eax*1]
mov eax,DWORD PTR [ebp-0x8]
lea edx,[eax+0x1]
mov eax,DWORD PTR [ebp+0x8]
add eax,edx
movzx eax,BYTE PTR [eax]
movsx edx,al
mov ecx,DWORD PTR [ebp-0x8]
mov eax,DWORD PTR [ebp+0x8]
add eax,ecx
movzx eax,BYTE PTR [eax]
movsx eax,al
sub edx,eax
mov eax,edx
add eax,ebx
mov DWORD PTR [ebp-0x10],eax
add DWORD PTR [ebp-0x8],0x1
asm4_138:
mov eax,DWORD PTR [ebp-0xc]
sub eax,0x1
cmp DWORD PTR [ebp-0x8],eax
jl asm4_51
mov eax,DWORD PTR [ebp-0x10]
add esp,0x10
pop ebx
pop ebp
ret
生成可执行文件
其基本思路很简单——就是将两个部分皆编译、汇编成目标文件,然后进行链接即可,从而生成正常的可执行文件。
对于C部分,其生成很简单;关键问题在于给定的汇编文件生成目标文件。如果此时直接执行gcc asm4.S
,则程序会给出编译错误等信息。
其原因也很简单:虽然这是一份正确的汇编代码,但是其使用Intel格式书写;而一般编译器默认使用AT&T格式进行编译和汇编,从而导致无法正常生成目标文件;除此之外,该汇编代码部分还需要声明其符号,方便进行调用。
因此修改过的汇编代码如下所示
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
65 noprefix
asm4
asm4:
push ebp
mov ebp,esp
push ebx
sub esp,0x10
mov DWORD PTR [ebp-0x10],0x246
mov DWORD PTR [ebp-0xc],0x0
jmp 0x518 <asm4+27>
asm4_23:
add DWORD PTR [ebp-0xc],0x1
asm4_27:
mov edx,DWORD PTR [ebp-0xc]
mov eax,DWORD PTR [ebp+0x8]
add eax,edx
movzx eax,BYTE PTR [eax]
test al,al
jne asm4_23
mov DWORD PTR [ebp-0x8],0x1
jmp asm4_138
asm4_51:
mov edx,DWORD PTR [ebp-0x8]
mov eax,DWORD PTR [ebp+0x8]
add eax,edx
movzx eax,BYTE PTR [eax]
movsx edx,al
mov eax,DWORD PTR [ebp-0x8]
lea ecx,[eax-0x1]
mov eax,DWORD PTR [ebp+0x8]
add eax,ecx
movzx eax,BYTE PTR [eax]
movsx eax,al
sub edx,eax
mov eax,edx
mov edx,eax
mov eax,DWORD PTR [ebp-0x10]
lea ebx,[edx+eax*1]
mov eax,DWORD PTR [ebp-0x8]
lea edx,[eax+0x1]
mov eax,DWORD PTR [ebp+0x8]
add eax,edx
movzx eax,BYTE PTR [eax]
movsx edx,al
mov ecx,DWORD PTR [ebp-0x8]
mov eax,DWORD PTR [ebp+0x8]
add eax,ecx
movzx eax,BYTE PTR [eax]
movsx eax,al
sub edx,eax
mov eax,edx
add eax,ebx
mov DWORD PTR [ebp-0x10],eax
add DWORD PTR [ebp-0x8],0x1
asm4_138:
mov eax,DWORD PTR [ebp-0xc]
sub eax,0x1
cmp DWORD PTR [ebp-0x8],eax
jl asm4_51
mov eax,DWORD PTR [ebp-0x10]
add esp,0x10
pop ebx
pop ebp
ret
通过添加上面两个注解,方便编译器等进行编译和链接。
其最后编译和链接时,仍需要传递相关的参数,表明采用Intel格式的汇编代码,如下所示
1
2gcc -m32 -c -masm=intel asm4.S
gcc -m32 asm4.S exp.c
最后执行,结果如下所示
1
2$ ./a.out
0x1d0