Easy Unpack

ReversingKr UnpackMe
Find the OEP.
ex) 00401000

Study

  • OEP: Original Entry Point
    • first instruction of the program’s real code.

Packing && Unpacking

  • Packing: Like zip-ing an executable.

Finding the entry point (OEP) is essential to the Unpacking! It’s how you find the actual binary.

  • Structure of packed program

    • New packer’s Header
    • Compressed binary
    • Stub (Decompressor)
  • Process of Unpacking

    1. Header : Jmp to Stub code.
    2. Stub : Decompresses the compressed binary.
    3. Decompressed binary : Jmp to the binary.

How Packed binary looks like — x32dbg

tmxklab 윈도우 실행파일 구조(PE파일) 블로그 참고

  • AddresssOfEntryPoint : Where the code starts. (after mapping to the memory)

AddressOfEntryPoint

  • bp-list (Possible points where Unpacking might happen.)
- VirtualProtect
- NtProtectVirtualMemory
- VirtualAlloc
- NtAllocateVirtualMemory
- NtWriteVirtualMemory

Continue the process… (f9)

VirtualProtect hit

BOOL VirtualProtect(
  [in]  LPVOID lpAddress,
  [in]  SIZE_T dwSize,
  [in]  DWORD  flNewProtect,
  [out] PDWORD lpflOldProtect
);

VirtualProtect args

-> Allow read/write for 00405000 ~ 00406000. (Maybe the unpack overwrite the sections??)

  • After the final VirtualProtect() call, the process jmp to 00401150.

Jump to 00401150

  • GetVersion(), GetCommandLineA(), GetStartupInfoA()

    • These functions runs on a program start-up!
  • The process reaches 00401219 and JMP to 00401000.

Jump to 00401000

  • CreateWindowExA, GetMessageA

  • a blank window pops up!

Blank window

How to Unpack using IDA

  1. Select IDA windows debugger from the “Debugger options” menu

IDA debugger

  1. Start Process
  2. Run the binary
  3. Find ”…Easy_UnpackMe.exe” in the “Modules” tab. Get the address.
  4. File -> Script Command (“Cut out ”)
import ida_bytes

output_file = "dumped_code.bin"

# Define the range
start_ea = 0x400000
end_ea = 0x40A680
size = end_ea - start_ea

data = ida_bytes.get_bytes(start_ea, size)

if data:
    with open(output_file, "wb") as f:
        f.write(data)
    print(f"Successfully dumped {len(data)} bytes to {output_file}")
else:
    print("Failed to read memory. Check if the addresses are valid.")

IDA dump

Side-hustle

How .exe looks is made? The structure?

hello.exe

  • Install MSYS2 for cpp compile.

MSYS2

Solution

Easy_UnpackMe.exe: PE32 executable (GUI) Intel 80386, for MS Windows, 5 sections
  1. Find functions like below which are indicator of where the unpacked be placed.
- VirtualProtect
- NtProtectVirtualMemory
- VirtualAlloc
- NtAllocateVirtualMemory
- NtWriteVirtualMemory

VirtualProtect args

  • Can check that VirtualProtect() allows read/write for 00401000 ~ 00405000 && 00406000 ~ 00409000 which are original place of where easy_unpackme.exe is.

Sections

  1. After final call of VirtualProtect(), the process JMP to 00401150.

Jump to 00401150

  • GetVersion(), GetCommandLineA(), GetStartupInfoA()
    • These functions usually runs on a program start-up!
  1. The process reaches 00401219 and JMP to 00401000.

Jump to 00401000

  • CreateWindowExA, GetMessageA
    • Which are for initializing Windows GUI
  1. And after some f8 blank window pops up.

Blank window

Hence I can conclude that 00401150

Btw…

The .Gogi, .Gwan sections are named after the creator of reversing.kr “고기완”.

Flag

00401150