文章总结: 本文推荐Windowsx64汇编与Shellcode入门教程,并展示了通过汇编动态获取kernel32基址、解析导出表调用WinExec执行calc.exe的代码实例。作者指出汇编难点在于PE结构、TEB与PEB等底层知识,鼓励读者坚持学习。
综合评分: 74
文章分类: 二进制安全,漏洞POC,逆向分析,实战经验
Windows x64汇编
原创
ybdt
ybdt
卡卡罗特取西经
2026年3月13日 22:18
吉林
学完王爽老师的Windows 16位汇编、罗云彬老师的Windows 32位汇编,最后就是Windows x64汇编,下面这个系列是我觉得不错的学习资源
【x64汇编与shellcode入门教程 01】https://mp.weixin.qq.com/s/HzEWKEpYpeBNJyk4IEll2g?scene=1【x64汇编与shellcode入门教程 02】https://mp.weixin.qq.com/s/vEfsmgBpEOJSzvXcvnEtUA?scene=1【x64汇编与shellcode入门教程 03】https://mp.weixin.qq.com/s/bJnqwt0_9rQCmaYZFrcFKg?scene=1【x64汇编与shellcode入门教程 04】https://mp.weixin.qq.com/s/-SEK85Fflt-Gr_Km9YcD3w?scene=1【x64汇编与shellcode入门教程 05】https://mp.weixin.qq.com/s/xC02bij37DTr_j4arJi_ag?scene=1【x64汇编与shellcode入门教程 06】https://mp.weixin.qq.com/s/db2pQXBx44IF4Dst0hw9sQ?scene=1【x64汇编与shellcode入门教程 07】https://mp.weixin.qq.com/s/AmjTv9wzFqzV1GKZYUecNQ
原文在这里:https://g3tsyst3m.com/shellcoding/assembly/debugging/x64-Assembly-and-Shellcoding-101/
翻译的质量不错,都很准确,当然你想看原文也可以
直接上代码,Windows x64汇编实现动态获取kernel32.dll地址,解析kernel32.dll导出表后定位WinExec,最后通过WinExec执行calc.exe
代码中包含了详细注释,我就不再赘述解释了
; nasm -fwin64 x64findkernel32.asm; ld -m i386pep -o x64findkernel32.exe x64findkernel32.obj
BITS 64SECTION .textglobal mainmain:
; get the base address of kernel32.dll by gs segment registersub rsp, 0x28and rsp, 0xfffffffffffffff0xor rcx, rcx ; rcx = 0 mov rax, [gs:rcx + 0x60] ; gs contain the base address of TEB, and offset 0x60 is the base address of PEBmov rax, [rax + 0x18] ; offset 0x18 is the base address of PEB->Ldrmov rsi, [rax + 0x10] ; offset 0x10 is the base address of PEB->Ldr->InLoadOrderModuleListmov rsi, [rsi] ; jump to next node of linked list PEB->Ldr->InLoadOrderModuleList, ntdll.dllmov rsi, [rsi] ; jump to next node of linked list PEB->Ldr->InLoadOrderModuleList, kernel32.dllmov rbx, [rsi + 0x30] ; offset 0x30 is the base address of kernel32.dllmov r8, rbx ; the value of rbx assign to r8
; parse pe file header and export table to locate WinExec addressmov ebx, [rbx+0x3C] ; pe file offset 0x3c contains nt headers addressadd rbx, r8 ; relative address + base addressmov edx, [rbx+0x88] ; nt headers offset 0x88 contains export directory addressadd rdx, r8 ; relative address + base addressmov r10d, [rdx+0x14] ; Total count for number of functionsxor r11, r11 ; clear R11 mov r11d, [rdx+0x20] ; AddressOfNames = RVAadd r11, r8 ; AddressOfNames = VMAmov rcx, r10 ; setup loop countermov rax, 0x00636578456E6957 ; "WinExec" string NULL terminated with a '0' push rax ; push to the stackmov rax, rsp ; move stack pointer to our WinExec string into RAXadd rsp, 8 ; keep with 16 byte stack alignment
kernel32findfunction: jecxz FunctionNameNotFound ; If ecx is zero (function not found), set breakpoint xor ebx, ebx ; Zero EBX mov ebx, [r11+rcx*4] ; EBX = RVA for first AddressOfName add rbx, r8 ; RBX = Function name VMA / add kernel32 base address to RVA to get WinApi name dec rcx ; Decrement our loop by one, this goes from Z to A mov r9, qword [rax] ; R9 = "WinExec" cmp [rbx], r9 ; Compare all bytes jz FunctionNameFound ; jump if zero flag is set (found function name!) jnz kernel32findfunction ; didn't find the name, so keep loopin til we do!
FunctionNameFound: push rcx jmp OrdinalLookupSetup
FunctionNameNotFound: int3
OrdinalLookupSetup: pop r15 js OrdinalLookup
OrdinalLookup: mov rcx, r15 ; move our function's place into RCX xor r11, r11 ; clear R11 for use mov r11d, [rdx+0x24] ; AddressOfNameOrdinals = RVA add r11, r8 ; AddressOfNameOrdinals = VMA inc rcx mov r13w, [r11+rcx*2] ; AddressOfNameOrdinals + Counter. RCX = counter xor r11, r11 mov r11d, [rdx+0x1c] ; AddressOfFunctions = RVA add r11, r8 ; AddressOfFunctions VMA in R11. Kernel32+RVA for function addresses mov eax, [r11+r13*4] ; function RVA. add rax, r8 ; Found the WinExec Api address!!! push rax ; Store function addresses by pushing it temporarily js executeit
; call WinExecexecuteit:pop r15 ; address for WinExecmov rax, 0x00 ; push null string terminator '0'push rax ; push it onto the stackmov rax, 0x6578652E636C6163 ; move string 'calc.exe' into RAX push rax ; push string + null terminator to stackmov rcx, rsp ; RDX points to stack pointer "WinExec" (1st parameter))mov rdx, 1 ; move 1 (show window parameter) into RDX (2nd parameter)sub rsp, 0x30 ; align stack 16 bytes and allow for proper setup for shadow space demandscall r15 ; Call WinExec!!
说一点感悟,常说的汇编难,其实难在它背后藏了很多知识,比如Windows PE中的导出表、再比如通过TEB、PEB的结构体,这些不懂的话,肯定看不懂汇编,不过路虽远,行则将至,再难的知识只要去学也能学会
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:卡卡罗特取西经 ybdt
ybdt《Windows x64汇编》