Suninatas Game 27

challenges

Game 27

We have an intercepted message containing hidden x86 shellcode. The challenge is to extract the secret by emulating the code.

The message file contains x86 machine code that, when executed, pushes characters onto the stack one by one to form the flag. Use the Unicorn Engine to emulate x86 code and monitor stack writes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#!/usr/bin/env python3
"""
x86 Emulation using Unicorn Engine to extract flag characters
pushed onto the stack during code execution.
"""

import sys
from unicorn import *
from unicorn.x86_const import *

CODE_FILE = 'message.txt'
BASE_ADDRESS = 0x1000000
STACK_ADDRESS = 0x2000000
MEM_SIZE = 2 * 1024 * 1024

flag_chars = []

def hook_mem_write(uc, access, address, size, value, user_data):
"""Capture stack writes (PUSH instructions) and extract characters."""
if access == UC_MEM_WRITE:
try:
char = chr(value)
if char.isprintable():
flag_chars.append(char)
print(f"[+] Pushed: '{char}' (0x{value:02x})")
except Exception:
pass

def main():
# Load shellcode
try:
with open(CODE_FILE, 'rb') as f:
code = f.read()
except FileNotFoundError:
print(f"Error: {CODE_FILE} not found.")
sys.exit(1)

print(f"Emulating x86 code ({len(code)} bytes)...")

try:
# Initialize x86 32-bit emulator
mu = Uc(UC_ARCH_X86, UC_MODE_32)

# Map memory regions
mu.mem_map(BASE_ADDRESS, MEM_SIZE)
mu.mem_map(STACK_ADDRESS, MEM_SIZE)

# Load code
mu.mem_write(BASE_ADDRESS, code)

# Initialize registers
mu.reg_write(UC_X86_REG_EAX, 0x0)
mu.reg_write(UC_X86_REG_ESP, STACK_ADDRESS + (MEM_SIZE // 2))

# Hook memory writes to capture pushed characters
mu.hook_add(UC_HOOK_MEM_WRITE, hook_mem_write)

# Execute
mu.emu_start(BASE_ADDRESS, BASE_ADDRESS + len(code))

except UcError as e:
# Emulation ends with an error when code runs off or lacks exit syscall
print(f"Emulation stopped: {e}")

# Output results
if flag_chars:
print(f"\n{'='*20}")
print(f"Extracted Flag: {''.join(flag_chars)}")
print(f"{'='*20}")

if __name__ == '__main__':
main()

Running the emulator extracts characters pushed during execution:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[+] Pushed: 'k' (0x6b)
[+] Pushed: 'e' (0x65)
[+] Pushed: 'y' (0x79)
[+] Pushed: '_' (0x5f)
[+] Pushed: 'i' (0x69)
[+] Pushed: 's' (0x73)
[+] Pushed: '_' (0x5f)
[+] Pushed: 'a' (0x61)
[+] Pushed: 'c' (0x63)
[+] Pushed: 'c' (0x63)
[+] Pushed: 'b' (0x62)
[+] Pushed: 'g' (0x67)
[+] Pushed: 'g' (0x67)
[+] Pushed: 'j' (0x6a)

====================
Extracted Flag: key_is_accbggj
====================
accbggj