基本信息
Category: Pwnable Points: 400 Solves: TODO Description:
- Binary : http://binary.grayhash.com/6c5c199232567d00314a684d0123b11c/steak
- Server : 54.64.101.236
- Port : TCP 8888
- OS : Ubuntu 14.04.2 LTS x86-64 Just overflow.
- 有一个栈溢出,非常短的二进制文件
开了Stack Canary和NX

如何解决
主要是三个点
- argv[0] leak
- RC4
- Shared Library Injection
初始检查
直接运行会产生SIGSEGV,似乎缺少能够让它正常运行的东西


用strace确认
添加env -i以防万一和清除环境变量

可以看出需要一个steak用户目录以及flag文件

创建对应用户及文件
1 | sudo adduser steak |
之后测试运行,大概就是接收stdin,sleep,结束,这样的流程

vmmap

- 低位是.text .data .bss等区域,这部分地址是固定的
- 高位是library,mapped,vdso,stack之类,程序正常运行必要的东西。如果开启了ASLR,这部分地址会受到影响。gdb运行下ASLR会暂时失效。
beef_steak解析
静态分析



整个流程大概就是,从flag文件读取内容作为key,对stdin内容进行RC4加密,之后与特定内容进行比较,相等则执行system("/bin/cat > ./message");
,不相等puts("I don't like that!");
RC4的key是flag
- key最大可能有40字节,理论上无法破解
- 因为我们不知道key,所以无法通过特定字符串的比较
- 也就无法调用system
存在栈溢出
- 缓冲区是40字节
- 读取了512字节
- 但是存在canary

这个问题符合argv[0] leak情况
- Stack Canary
- 没有PIE
- canary保护的函数有足够的溢出空间
- 可以读取glibc显示的错误信息
那应该泄漏哪些东西呢?
- 如果能够泄漏RC4相关内容就太棒了
- 如果成功,就能够调用system()
- 那么RC4相关内容在哪里
key(=flag)和表S,存在于.bss区域中
- 但是,key最初被KSA使用后立即清零。也就谁说,只有表S可以泄漏
- 表S的地址是0x602160

泄漏RC4内部表
使用argv[0] leak泄漏0x602160的内容
- 尝试计算出准确距离,精确泄漏

- 在返回之前设置断点,查看状态
- 这里设置在0x400CC8,返回之前必定会执行这里

正常运行,确认stack状态:


可以计算出输入与argv[0]之间距离为280字节

使用280个”\0” + 0x602160比较好
- 使用”\0”而不是”A”,因为RC4_PRGA()中使用了strlen(),这样导致返回0,输入的数据不会经过RC4加密
- 因为没有进入循环,没有任何字节被修改,S也不会变化

注意小端序问题,测试运行:

实际上,这些就是泄漏出来的表S内容
exploit
argv[0] leak

因为RC4状态表会出现一次\x00导致后面内容不显示,所以需要进行一点处理


这样我们可以获取到本地测试环境的RC4状态表

RC4解密
我们已经获得了状态表S,通过S生成伪随机数序列,与密文异或就能够获得明文
这样我们使用获取的明文作为输入,运行程序,就能够执行system()


getshell
这样我们相当于已经可以写入任意内容到文件了,应该也就能够进行Shared Library Injection
可以按这个流程操作:
- 第一次将mylib.so作为message上传
- 第二次伪造LD_PRELOAD=./message环境变量
到envp的距离

也就是说,我们如果想修改envp[0],只需要填充296字节

那么字符串LD_PRELOAD=./message应该放在哪呢
因为RC4的输入是栈上的buffer,输出是全局变量output,全局变量的地址固定,可以使用这个


需要注意最初25个字节是strcmp进行比较来判断是否执行system
整个攻击流程大概是这样:

exploit


参考
只搜到这一篇writeup,结合以上内容直接看代码吧:
1 | from pwn import * |