shellcode生成框架
因为vs编译后自己会生成很多东西,我们稍微配置下


先获取kernel32基址
__declspec(naked) DWORD getKernel32()
{
  __asm
  {
    mov eax, fs:[30h]  //PEB
      mov eax, [eax + 0ch]  //PEB->Ldr
      mov eax, [eax + 14h]  //PEB->Ldr.InMemOrder
      mov eax, [eax]  //第二个模块
      mov eax, [eax]  //第三个模块
      mov eax, [eax + 10h]  //base address
      ret
  }
}
获取GetProcAddress函数地址
FARPROC  getProcAddress(HMODULE hModuleBase)
{
  PIMAGE_DOS_HEADER lpDosHeader = (PIMAGE_DOS_HEADER)hModuleBase;
  PIMAGE_NT_HEADERS32 lpNtHeader = (PIMAGE_NT_HEADERS32)((DWORD)hModuleBase + lpDosHeader->e_lfanew);
  if (!lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)
  {
    return NULL;
  }
  if (!lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
  {
    return NULL;
  }
  PIMAGE_EXPORT_DIRECTORY lpExports = (PIMAGE_EXPORT_DIRECTORY)((DWORD)hModuleBase + (DWORD)lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
  PDWORD lpdwFunName = (PDWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfNames);
  PWORD lpwOrd = (PWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfNameOrdinals);
  PDWORD lpdwFunAddr = (PDWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfFunctions);
  DWORD dwLoop = 0;
  FARPROC pRet = NULL;
  for (; dwLoop <= lpExports->NumberOfNames - 1; dwLoop++)
  {
    char* pFunName = (char*)(lpdwFunName[dwLoop] + (DWORD)hModuleBase);
    if (pFunName[0] == 'G' &&
      pFunName[1] == 'e' &&
      pFunName[2] == 't' &&
      pFunName[3] == 'P' &&
      pFunName[4] == 'r' &&
      pFunName[5] == 'o' &&
      pFunName[6] == 'c' &&
      pFunName[7] == 'A' &&
      pFunName[8] == 'd' &&
      pFunName[9] == 'd' &&
      pFunName[10] == 'r' &&
      pFunName[11] == 'e' &&
      pFunName[12] == 's' &&
      pFunName[13] == 's')
    {
      pRet = (FARPROC)(lpdwFunAddr[lpwOrd[dwLoop]] + (DWORD)hModuleBase);
      break;
    }
  }
  return pRet;
}
首先定义ms-dos头
//some code……
PIMAGE_DOS_HEADER lpDosHeader = (PIMAGE_DOS_HEADER)hModuleBase;
然后得到pe头image-nt-header
//some code……
PIMAGE_NT_HEADERS32 lpNtHeader = (PIMAGE_NT_HEADERS32)((DWORD)hModuleBase + lpDosHeader->e_lfanew);
直接dos头加e_lfanew,这里因为是c++代码就不用汇编写入偏移地址3c等等,后面也要贴上汇编代码,结合一起看其实也不难理解
//some code……
if (!lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)
  {
    return NULL;
  }
  if (!lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
  {
    return NULL;
  }
这里还是贴上这个图(转载的图)


在pe-option-header里面存在一个size和virualaddress,我们还是主要看 VirtualAddress(相对虚拟地址)字段,我们得到这个结构体
//some code……
PIMAGE_EXPORT_DIRECTORY lpExports = (PIMAGE_EXPORT_DIRECTORY)((DWORD)hModuleBase + (DWORD)lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
我们将会使用这个结构的如下字段:
AddressOfFunctions:指向一个DWORD类型的数组,每个数组元素指向一个函数地址。AddressOfNames:指向一个DWORD类型的数组,每个数组元素指向一个函数名称的字符串。AddressOfNameOrdinals:指向一个WORD类型的数组,每个数组元素表示相应函数的排列序号(16位整数)
//some code……
PDWORD lpdwFunName = (PDWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfNames);
  PWORD lpwOrd = (PWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfNameOrdinals);
  PDWORD lpdwFunAddr = (PDWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfFunctions);
然后判断是否为GetProcAddress函数是就返回
//some code……
 DWORD dwLoop = 0;
  FARPROC pRet = NULL;
  for (; dwLoop <= lpExports->NumberOfNames - 1; dwLoop++)
  {
    char* pFunName = (char*)(lpdwFunName[dwLoop] + (DWORD)hModuleBase);
    if (pFunName[0] == 'G' &&
      pFunName[1] == 'e' &&
      pFunName[2] == 't' &&
      pFunName[3] == 'P' &&
      pFunName[4] == 'r' &&
      pFunName[5] == 'o' &&
      pFunName[6] == 'c' &&
      pFunName[7] == 'A' &&
      pFunName[8] == 'd' &&
      pFunName[9] == 'd' &&
      pFunName[10] == 'r' &&
      pFunName[11] == 'e' &&
      pFunName[12] == 's' &&
      pFunName[13] == 's')
    {
      pRet = (FARPROC)(lpdwFunAddr[lpwOrd[dwLoop]] + (DWORD)hModuleBase);
      break;
    }
  }
  return pRet;
这里用到了导出表里面得一个single每次查找一次就+1这里返回回去就是-1然后逐一进行判断
头部再定义一下
//some code……
DWORD getKernel32();
FARPROC  getProcAddress(HMODULE hModuleBase);
这里kernel32.dll和GetProcess函数地址都得到了后面就好说了
这里我们举CreateFile和Messagebox例子
这里是原来应该得写法
//some code……
typedef HANDLE(WINAPI *FN_CreateFileA)(
    _In_ LPCSTR lpFileName,
    _In_ DWORD dwDesiredAccess,
    _In_ DWORD dwShareMode,
    _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    _In_ DWORD dwCreationDisposition,
    _In_ DWORD dwFlagsAndAttributes,
    _In_opt_ HANDLE hTemplateFile
    );
  FN_CreateFileA fn_CreateFileA = (FN_CreateFileA)GetProcAddress(LoadLibraryA("kernel32.dll"), "CreateFileA");
我们先处理LoadLibraryA("kernel32.dll")
先得到GetProcAddress
typedef FARPROC(WINAPI * FN_GetProcAddress)(
    _In_ HMODULE hModule,
    _In_ LPCSTR lpProcName
    );
  FN_GetProcAddress fn_GetProcAddress = (FN_GetProcAddress)getProcAddress((HMODULE)getKernel32());
然后把"CreateFileA"字符串替换了
char szCreateFile[] = { 'C', 'r', 'e', 'a', 't', 'e', 'F', 'i', 'l', 'e', 'A',0 };
这里完整为
typedef FARPROC(WINAPI * FN_GetProcAddress)(
    _In_ HMODULE hModule,
    _In_ LPCSTR lpProcName
    );
  FN_GetProcAddress fn_GetProcAddress = (FN_GetProcAddress)getProcAddress((HMODULE)getKernel32());
  typedef HANDLE(WINAPI *FN_CreateFileA)(
    _In_ LPCSTR lpFileName,
    _In_ DWORD dwDesiredAccess,
    _In_ DWORD dwShareMode,
    _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    _In_ DWORD dwCreationDisposition,
    _In_ DWORD dwFlagsAndAttributes,
    _In_opt_ HANDLE hTemplateFile
    );
  char szCreateFile[] = { 'C', 'r', 'e', 'a', 't', 'e', 'F', 'i', 'l', 'e', 'A',0 };
  FN_CreateFileA fn_CreateFileA = (FN_CreateFileA)fn_GetProcAddress((HMODULE)getKernel32(), szCreateFile);
  char szNewFile[] = { '1', '.', 't', 'x', 't', '\0' };
  fn_CreateFileA(szNewFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
下面为MessageBoxA
typedef HMODULE (WINAPI* FN_LoadLibraryA)(
    _In_ LPCSTR lpLibFileName
    );
    char szLoadLibraryA[] = { 'L', 'o', 'a', 'd', 'L', 'i', 'b', 'r', 'a', 'r', 'y', 'A', 0 };
    FN_LoadLibraryA fn_LoadLibraryA = (FN_LoadLibraryA)fn_GetProcAddress((HMODULE)getKernel32(), szLoadLibraryA);
  typedef int (WINAPI* FN_MessageBoxA)(
    _In_opt_ HWND hWnd,
    _In_opt_ LPCSTR lpText,
    _In_opt_ LPCSTR lpCaption,
    _In_ UINT uType);
  //正常写法
  //FN_MessageBoxA fn_MessageBoxA = (FN_MessageBoxA)GetProcAddress(LoadLibraryA("user32.dll"), "MessageBoxA");
  char szUser32[] = { 'U', 's', 'e', 'r', '3', '2', '.', 'd', 'l', 'l', 0 };
  char szMessageboxA[] = { 'M', 'e', 's', 's', 'a', 'g', 'e', 'B', 'o', 'x', 'A', 0 };
  FN_MessageBoxA fn_MessageBoxA = (FN_MessageBoxA)fn_GetProcAddress(fn_LoadLibraryA(szUser32), szMessageboxA);
  char szHello[] = { 'y', 'i', 'c', 'u', 'n', 'y', 'i', 'y', 'e', 0 };
  char szTip[] = { 't', 'i', 'p', 0 };
  fn_MessageBoxA(NULL, szHello, szTip, MB_OK);
看看正常写法
FN_MessageBoxA fn_MessageBoxA = (FN_MessageBoxA)GetProcAddress(LoadLibraryA("user32.dll"), "MessageBoxA");
因为获取得是user32.dll而不是直接一样得kernel32.dll所以我们要获取下LoadLibraryA得地址
typedef HMODULE (WINAPI* FN_LoadLibraryA)(
    _In_ LPCSTR lpLibFileName
    );
    char szLoadLibraryA[] = { 'L', 'o', 'a', 'd', 'L', 'i', 'b', 'r', 'a', 'r', 'y', 'A', 0 };
    FN_LoadLibraryA fn_LoadLibraryA = (FN_LoadLibraryA)fn_GetProcAddress((HMODULE)getKernel32(), szLoadLibraryA);
然后就是获取MessageBoxA得地址
typedef int (WINAPI* FN_MessageBoxA)(
    _In_opt_ HWND hWnd,
    _In_opt_ LPCSTR lpText,
    _In_opt_ LPCSTR lpCaption,
    _In_ UINT uType);
  //正常写法
  //FN_MessageBoxA fn_MessageBoxA = (FN_MessageBoxA)GetProcAddress(LoadLibraryA("user32.dll"), "MessageBoxA");
  char szUser32[] = { 'U', 's', 'e', 'r', '3', '2', '.', 'd', 'l', 'l', 0 };
  char szMessageboxA[] = { 'M', 'e', 's', 's', 'a', 'g', 'e', 'B', 'o', 'x', 'A', 0 };
  FN_MessageBoxA fn_MessageBoxA = (FN_MessageBoxA)fn_GetProcAddress(fn_LoadLibraryA(szUser32), szMessageboxA);
最后再输出
char szHello[] = { 'y', 'i', 'c', 'u', 'n', 'y', 'i', 'y', 'e', 0 };
  char szTip[] = { 't', 'i', 'p', 0 };
  fn_MessageBoxA(NULL, szHello, szTip, MB_OK);
运行结果可以看到没什么问题

然后我们peid打开

看下偏移是400然后我们ue打开然后找到对应得偏移地址复制这个16进制就是我们需要的shellcode,然后把shellcode插入到进程中执行就可以了,这里我们可以静态得插入到未执行得exe文件中,或者动态的插入到正在执行得进程的内存中,这里我们试试插入到未执行的exe文件中
558BEC83EC4C56E8E40000008BC8E8FD0000008BF0C745D0437265618D45D0C745D47465466950C745D86C654100E8BD00000050FFD66A006A006A026A006A0068000000408D4DF4C745F4312E74785166C745F87400FFD08D45B4C745B44C6F616450C745B84C696272C745BC61727941C645C000E87600000050FFD68D4DC4C745DC55736572518D4DDCC745E033322E645166C745E46C6CC645E600C745C44D657373C745C861676542C745CC6F784100FFD050FFD66A008D4DFCC745E879696375518D4DE8C745EC6E796979516A0066C745F06500C745FC74697000FFD033C05E8BE55DC3CCCCCCCCCCCCCCCCCC64A1300000008B400C8B40148B008B008B4010C3CCCCCCCCCCCCCCCCCCCCCCCC558BEC8BD183EC088B423C837C107C00750633C08BE55DC38B44107885C074F28B4C102403CA538B5C1020894DFC03DA8B4C101C568B74101803CA57894DF833FF33C94E8B048B03C2803847754E80780165754880780274754280780350753C8078047275368078056F753080780663752A80780741752480780864751E80780964751880780A72751280780B65750C80780C73750680780D73740E413BCE76A38BC75F5E5B8BE55DC38B45FC8B7DF80FB704488B3C8703FA8BC75F5E5B8BE55DC30000
这里是29行+4个,我用以前写的端口扫描做测试
先看看入口的文件偏移

000C23A0然后用winhex打开
然后我们转到偏移地址

修改同样大小他shellcode替换了,所以只要运行这个exe就会运行我们的shellcode

然后我们保存运行

说明我们的shellcode插入了这个exe中,执行他就执行了我们的shellcode
我们也可以把他shellcode生成为一个bin文件再写个加载器运行
shellcode生成框架的更多相关文章
- windows:shellcode生成框架和加载
		https://www.cnblogs.com/theseventhson/p/13194646.html 分享了shellcode 的基本原理,核心思路是动态获取GetProcAddress和Lo ... 
- 深入浅出Java探针技术2---java字节码生成框架ASM、Javassist和byte buddy的使用
		目前Java字节码生成框架大致有ASM.Javassist和byte buddy三种 ASM框架介绍及使用 1.ASM介绍 ASM是一种Java字节码操控框架,能够以二进制形式修改已有的类或是生成类, ... 
- react-static 基于react 渐进式静态站点生成框架
		react-static 是一个不错的基于react 开发的静态站点生成框架,可以用来替代create-react-app 包含的特性 100% react 很快的构建以及性能 自动代码以及数据分离 ... 
- gradle下mybatis自动生成框架的使用
		自动生成框架的意义 主要为了解决人为添加mapper,模型等工作,减少错误,提交效率! 添加引用build.gradle configurations { mybatisGenerator } myb ... 
- MSFVENOM SHELLCODE生成备忘录
		MSFVENOM SHELLCODE生成 通用Shellcode msfvenom -a x86 --platform windows -p windows/shell_reverse_tcp LHO ... 
- Go 语言,开源服务端代码自动生成 框架 - EasyGoServer
		EasyGoServer 作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblog ... 
- android studio 插件开发(自动生成框架代码插件)
		android studio 插件开发 起因 去年公司开始上新项目,正好android在架构这方面的讨论也开始多了起来,于是mvp架构模型就进入我们技术选择方案里面,mvp有很多好处,但是有一个非常麻 ... 
- 美团分布式ID生成框架Leaf源码分析及优化改进
		本文主要是对美团的分布式ID框架Leaf的原理进行介绍,针对Leaf原项目中的一些issue,对Leaf项目进行功能增强,问题修复及优化改进,改进后的项目地址在这里: Leaf项目改进计划 https ... 
- 优于 swagger 的 java markdown 文档自动生成框架-01-入门使用
		设计初衷 节约时间 Java 文档一直是一个大问题. 很多项目不写文档,即使写文档,对于开发人员来说也是非常痛苦的. 不写文档的缺点自不用多少,手动写文档的缺点也显而易见: 非常浪费时间,而且会出错. ... 
随机推荐
- machine vision plan
			以OpenCV+C#/C++为主,Halcon+C#/C++.LabVIEW+NI Vision,其他还不了解 目前:Halcon+C# 1.完成:测量定位,表面质量检测 2.完成1后开始:OpenC ... 
- vue项目打包配置多个测试环境与生产环境,用npm命令打出不同的资源包。
			1.找到package.json文件,找到script节点.再新增一个新的脚本命令 test 2.修改prod.env.js配置文件,npm_lifecycle_event代表返回当前执行的脚本名称, ... 
- Jmeter+Ant+jenkins实现api自动化测试的持续集成
			0基础上手教程 @jmeter的使用 jmeter是一个基于java语言编写的开源测试工具,广泛应用于接口测试,性能测试,自动化测试. 接口自动化的编写教程,将于后续分享. 问题一:为什么用ant,而 ... 
- 如何通过seo技术提高网站对用户的友好度
			http://www.wocaoseo.com/thread-129-1-1.html 今天的天气又是29度,眼看着满大街的人都穿着短袖和衬衣了,自己也再不能穿个厚厚的外套出去了,要不会被别人笑 ... 
- Selenium中核心属性以及方法
			一.操作定位元素 selenium提供了定位元素的API,这些方法都被定义在webDriver类中,需要以find开头, 例如:find_Element_by_id('') 
- 设计模式C++模板(Template)模式
			设计模式C++描述----02.模板(Template)模式(转载) 一. 问题 在面向对象系统的分析与设计过程中经常会遇到这样一种情况:对于某一个业务逻辑(算法实现)在不同的对象中有不同的细节实现, ... 
- e3mall商城的归纳总结10之freemarker的使用和sso单点登录系统的简介
			敬给读者的话 本节主要讲解freemarker的使用以及sso单点登录系统,两种技术都是比较先进的技术,freemarker是一个模板,主要生成一个静态静态,能更快的响应给用户,提高用户体验. 而ss ... 
- CobaltStrike与Metasploit联动配合
			利用CobaltStrike内置Socks功能 通过Beacon内置的Socks功能在VPS上开启代理端口,打通目标内网通道,之后将本地Metasploit直接带入目标内网,进行横向渗透. 首先,到已 ... 
- Apache Pulsar 社区周报:08-15 ~ 08-21
			关于 Apache Pulsar Apache Pulsar 是 Apache 软件基金会顶级项目,是下一代云原生分布式消息流平台,集消息.存储.轻量化函数式计算为一体,采用计算与存储分离架构设计,支 ... 
- 【Android】Android开发小功能,倒计时的实现。时间计时器倒计时功能。
			作者:程序员小冰,GitHub主页:https://github.com/QQ986945193 新浪微博:http://weibo.com/mcxiaobing 首先给大家看一下我们今天这个最终实现 ... 
