Shellcode1

The main function flow is the following:

1- Get the length of a string located at 0x404040 using Strlen

The string is the following:

addrs: 0x00404040 string: 2b:B*bbz"*iJriRi2zi*bzJ hex: \x32\x62\x0a\x3a\xdb\x9a\x42\x2a\x62\x62\x1a\x7a\x22\x2a\x69\x4a\x9a\x72\xa2\x69\x52\xaa\x9a\xa2\x69\x32\x7a\x92\x69\x2a\xc2\x82\x62\x7a\x4a\xa2\x9a\xeb\x00

2- Then it calls VirtualAlloc to make some space in memory with execution permissions (using the constant value for PAGE_EXECUTE_READWRITE)

Here the VirtualAlloc definition from Microsoft's docs:

LPVOID VirtualAlloc(

LPVOID lpAddress,

SIZE_T dwSize,

DWORD flAllocationType,

DWORD flProtect

);

3- Copies a section of 15 bytes from data to the allocated memory region. The section contains the following code:

; DATA XREF from entry0 (0x4022ce)

0x00404068 8b3e mov edi, dword [esi]

0x0040406a 8b4e04 mov ecx, dword [esi + 4]

┌─> 0x0040406d c0440fff05 rol byte [edi + ecx - 1], 5

└─< 0x00404072 e2f9 loop 0x40406d

0x00404074 c3 ret

4- Calls the code shown above. Here’s the exact instruction:

0x004022e5 ff9560ffffff call dword [s1]

The routine decodes the original string form the step 1 (located at 0x00404040) using a rotator decipher (rotating every piece 5 bits left). We can emulate this behavior outside the original program by putting together an assembly file that takes the string, decodes it and outputs the result:

global _start

section .text _start: jmp envSetup encodedFlagStart: db

0x32,0x62,0x0a,0x3a,0xdb,0x9a,0x42,0x2a,0x62,0x62,

0x1a,0x7a,0x22,0x2a,0x69,0x4a,0x9a,0x72,0xa2,0x69,

0x52,0xaa,0x9a,0xa2,0x69,0x32,0x7a,0x92,0x69,0x2a,

0xc2,0x82,0x62,0x7a,0x4a,0xa2,0x9a,0xeb,0x00

encodedFlagEnd: envSetup:

mov edi, encodedFlagStart

lea ecx, [encodedFlagEnd - encodedFlagStart] decodeByte:

rol byte [edi + ecx], 5

dec ecx

jns decodeByte printResult:

mov rax, 0x01

mov rdi, rax

mov rsi, encodedFlagStart

mov rdx, 43

syscall exit:

xor rbx, rbx

mov rax, 0x3c

syscall

I used a custom script to assemble and link the file. Nothing fancy, it just gets the job done. Here we can see the flag is output to the console: