attack lab记录

因为作者本人是在学校的希冀平台上做的,so以下的准备部分的内容适合学校的希冀平台~

准备部分

objdump -d ctarget > c.txt

Part I : ctarget

level 1

ctarget的流程大概就是执行test函数,然后输入字符串。这里level 1的要求是调用touch1函数即可,因此我们需要找到ctarget里getbuf函数的反汇编。

打开刚刚生成的c.txt文件,输入

/getbuf

来查找getbuf方法的汇编代码

这里借用其他博主的图来表示的更清楚

getbuf函数开辟了24字节的栈空间,函数里有用户自定义的8字节的数组,用户在8字节内可以随便输入,但是输入超过23字节,就会覆盖到调用者栈帧最下面的返回地址。这里我们的是开辟了40个字节的空间,只要我们输入的字符串将调用者的返回地址覆盖成我们想要它返回的地址即可。我们来看touch1的反汇编

发现touch1的首地址是 0x4016d1,注意我们这里要用小端法,即输入的字符串要写成d1 16这样,开辟的24字节空间里面填什么无所谓。最后我们可以填成这样:

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
d1 16 40

将该文件命名为1.1,之后执行代码

./hex2raw<1.1>1.1_raw

再运行

./ctarget<1.1_raw>

然后就🆗啦~

level 2

我们先打开c.txt,查看touch2的反汇编

/ touch2

大意还是一样的,调用touch2即成功。我们看见touch2传了一个参数,这个参数值如果等于cookie的话就成功。cookie的值在给定的文件cookie.txt里有,我的cookie是0x30bad0de。

回忆一下,函数的第一个参数放在 %rdi 寄存器里面,这里我们显然不能直接输入字符串,需要借助汇编语言来实现。具体解题思路如下:

  • 将正常的返回地址设置成为注入代码的地址,这次注入直接在栈顶注入,即设置为%rsp
  • cookie的值写在%rdi里
  • 获取touch2的首地址,这个已经有了
  • 要调用touch2,却不能用call jmp等命令,所以只能用ret弹出,在弹出之前要先把touch2地址压栈。

这里需要补充的是ret指令到底在做什么:

在CPU中有一个“PC”即程序寄存器,在 x86-64 中用%rip表示,它时刻指向将要执行的下一条指令在内存中的地址。而ret指令就相当于:

pop %rip

即把栈中存放的地址弹出作为下一条指令的地址。

因此我们的汇编代码为:

命令行里编译再查看其反汇编:

这三条指令地址我们就有了,就是每行反汇编最前面的一长串十六进制数字,接着我们去找%rsp在哪,借助gdb。

得到%rsp地址,然后写注入字符串就好了,字符串为 注入代码地址——无用字符——返回地址。

然后就可以啦~

level 3

本题与上题类似,不同点在于传的参数是一个字符串。先给出touch3的C语言代码

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);
}

touch3中调用了hexmatch,它的C语言代码为:

/* 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;
}

也就是说,要把cookie转换成对应的字符串传进去

注意第6行,s的位置是随机的,我们写在getbuf栈中的字符串很有可能被覆盖,一旦被覆盖就无法正常比较。

因此,考虑把cookie的字符串数据存在test的栈上,其它部分与上题相同,这里不再重复思路。

注入代码为:

我们期望的栈帧为:

逻辑如下:

  • getbuf执行ret,从栈中弹出返回地址,跳转到我们注入的代码
  • 代码执行,先将存在caller的栈中的字符串传给参数寄存器%rdi,再将touch3的地址压入栈中
  • 代码执行ret,从栈中弹出touch3指令,成功跳转

因此最终solution为:

攻击成功~

Part II : rtarget

在第二部分中,我们要攻击的是rtarget,它的代码内容与第一部分基本相同,但是攻击它却比第一部分要难得多,主要是因为它采用了两种策略来对抗缓冲区溢出攻击

  • 栈随机化。这段程序分配的栈的位置在每次运行时都是随机的,这就使我们无法确定在哪里插入代码
  • 限制可执行代码区域。它限制栈上存放的代码是不可执行的。

因此我们在这里需要使用的攻击策略是ROP:面向返回的程序设计,就是在已经存在的程序中找到特定的以ret结尾的指令序列为我们所用,称这样的代码段为gadget,把要用到部分的地址压入栈中,每次ret后又会取出一个新的gadget,于是这样就能形成一个程序链,实现我们的目的。

​​​​​​​

同时,有如下指令编码表:

level 1

本题的任务与Phase 2相同,都是要求返回到touch2函数,phase 2中用到的注入代码为:

我们根本不可能找到这种带特定立即数的gadget,只能思考其他办法。

首先,要做的是把 cookie 赋值给参数寄存器%rdi,考虑将 cookie 放在栈中,再用指令:

pop %rdi
ret

就能实现参数的赋值了,当ret后,从栈中取出来的程序地址再设置为touch2的地址就能成功解决本题

但是后来发现在farm中找不到这条指令的gadget,因此我们考虑在其他寄存器进行中转,用两个gadget:

popq %rax
ret
###############
movq %rax, %rdi
ret

因此栈帧情况大致如下:

逻辑如下:

  • getbuf执行ret,从栈中弹出返回地址,跳转到我们的gadget01
  • gadget01执行,将cookie弹出,赋值给%rax,然后执行ret,继续弹出返回地址,跳转到gadget2
  • gadget2执行,将cookie值成功赋值给参数寄存器%rdi,然后执行ret,继续弹出返回地址,跳转到touch2

首要问题是找到我们需要的gadget

先用如下指令得到target的汇编代码及字节级表示

objdump -d rtarget > rtarget.s

查表知,pop %rax58表示,于是查找58:(其中 90 表示“空”,可以忽略)

得到指令地址为0x401860

movq %rax, %rdi表示为48 89 c7,刚好能找到!

得到指令地址为0x401874

根据上图的栈帧,就能写出输入序列:​​​​​​​

攻击成功~

level 2

本题的任务与Phase 3相同,都是要求返回到touch3函数

level 3中用到的注入代码为:

其中0x556589c8是栈中cookie存放的地址。

而在本题中,栈的位置是随机的,把cookie存放在栈中似乎不太现实,但是我们又不得不这样做,那么有什么办法呢?只能在代码中获取%rsp的地址,然后根据偏移量来确定cookie的地址。想到这,思路就明晰了。

而farm中可以用来相加赋值的汇编只有一个:

因此我们要给rdi和rsi赋值基址(rsp)和偏移

查表,movq %rsp, xxx表示为48 89 xx,查找一下发现有一个可用的gadget

还真找到了,48 89 e0对应的汇编代码为

movq %rsp, %rax

而 movq %rax, xxx也只有一个 movq %rsp, %dri:

剩下部分流程与Phase 3一致,大体思路如下:

  • 先取得栈顶指针的位置
  • 取出存在栈中得偏移量的值
  • 通过lea (%rdi,%rsi,1),%rax得到 cookie 的地址
  • 将 cookie 的地址传给%rdi
  • 调用touch 3

由于gadget的限制,中间的细节需要根据自己的情况尝试,就不再一一列举了,直接给出我的查找结果:

farm里面查找:

​​​​​​​

以上farm里的内容找到对应的rtarget里的地址:

因此我的序列是:

Pass( •̀ >< •́ )y

  • 13
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值