windows:shellcode生成框架和加载
https://www.cnblogs.com/theseventhson/p/13194646.html 分享了shellcode 的基本原理,核心思路是动态获取GetProcAddress和LoadLibrary函数地址,再通过这两个函数获取其他windows dll提供的函数地址;需要注意的是shellcode不能有全局变量和字符串,只能用局部变量和字符数组替代,这样才能在函数执行时在栈动态分配存储空间,不会和目标进程现有的空间冲突。
实战中,通过这种方式生成shellcode技术上可行,但比较麻烦,需要改动的地方太多,下面介绍一种shellcode现成的框架,开发人员可直接在特定的地方添加特定的代码即可,简单、灵活、易用;
1、先介绍一下vs的编译顺序
一个大型的工程,往往有多个cpp文件组成,最后都被编译成一个exe文件,那么exe中那么多函数,这些函数都是怎么排序的了?
(1)文件之间:比如有多个文件,默认是按照文件名排序,比如先按照0-9排序,再按照a-z排序;下面默认先编译A.cpp,再编译B.cpp,最后编译main.c;但是也可以认为调整配置文件中的顺序,让B最先编译,A稍后编译,这样一来生成exe中函数顺序就按照这个来排序;

(2)文件内部:按照定义/实现的顺序;比如下面的例子:函数实现的顺序分别是main、FuncB、FuncA,那么编译器在生成exe时编译的顺序也是这样的。

上面说了这么多编译顺序,能用来干啥了?------> 确认shellcode 的范围和提取代码,比如上面用户把shellcode写进A和B函数,那么FuncA-FuncB者之间的代码都是shellcode,再调用CreateFile函数就能很容易保存到磁盘了;
2、shellcode框架介绍
(1)先来看看shellcode生成框架:四个文件起名很有讲究,这样一来编译器就会按照这个顺序来编译源文件了,生成的exe中也会按照这个顺序排列函数;
0.entry文件中,并不执行shellcode,只是通过shellcodeEnd-shellcodeStart 确认shellcode 的范围和起始地址,然后写入磁盘的bin文件;

(2)a.start: shellcodeStart函数直接jmp到shellcodeEntry;InitFuntions初始化需要用到的几个关键函数;最关键的shellcodeEntry函数:用户可以在这里添加shellcode的自定义逻辑;

这里的shellcodeStart函数,是个裸函数,仅有一行代码,就是jmp到shellcodeEntry,这么简单的功能,为啥不直接把shellcodeEntry的代码复制到这里来,从这里跳转的意义是啥?
- shellcodeStart在这里,生成shellcode的时候才能把最核心的getKernel32和getProcAddress函数包进来;
- 后续加载shellcode的时候会用call,那么需要从shellcode返回,这里是裸函数,没有ret,等后续shellcode所有的函数执行完后,最后一个ret刚好可以返回shellcode加载器,这里设计比较巧妙;
__declspec(naked) void ShellcodeStart()
{
__asm
{
jmp ShellcodeEntry
} }
(3)b.works:开发人员可以在这里自定义shellcode的执行逻辑(包装在单独的函数里),然后在上面的shellcodeEntry中调用该函数即可;

(4)最后一个z.end:收尾工作,目前是空白的,啥也没做;由于shellcode的范围是shellcodeEnd-shellcodeStart,所以shellcode在End这行代码已经截至,这个函数内部任何代码都不会被收录到shellcode,这里请注意;

上面是整个框架的简介,最核心的地方是a.start的shellcodeEntry和b.works,开发人员直接在这里添加自定义的处理逻辑就好,其他地方一般都不用更改了,整个框架的复用性非常好;编译的时候也能看到各个文件编译的顺序:

用IDA查看如下:函数的编译顺序确实是按照上面讲的顺序编译的:

3、shellcode代码加载
利用上述框架生成的shellcode,保存在磁盘bin文件,怎么加载和运行了?这里先介绍一个简单的方法:自己编写一个loader;
核心原理很简单:调用VirtualAlloc分配一段内存,然后把shellcode拷贝到这段内存,最后call跳转到shellcode执行;
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
int main(int argc, char* argv[])
{
HANDLE hFile = CreateFileA(argv[], GENERIC_READ, , NULL, OPEN_ALWAYS, , NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("Open File Error!%d\n", GetLastError());
return -;
}
DWORD dwSize;
dwSize = GetFileSize(hFile, NULL); LPVOID lpAddress = VirtualAlloc(NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (lpAddress == NULL)
{
printf("VirtualAlloc error:%d\n", GetLastError());
CloseHandle(hFile);
return -; }
DWORD dwRead;
ReadFile(hFile, lpAddress, dwSize, &dwRead, );
__asm
{
call lpAddress; }
_flushall();
system("pause");
return ;
}
用该加载器成功加载shellcode并运行:

4、这里的shellcode是自己loader加载的,运行空间也是loader分配的,容易被查出来;后续会介绍一些其他方法,比如把shellcode注入其他进程执行,增加被查找到的难度;
最后感谢这两个链接的作者(特别是视频介绍,由浅入深,通俗易懂),供初学者参考:
https://www.freebuf.com/articles/system/93983.html (有现成的工程供参考使用)
https://www.bilibili.com/video/BV1y4411k7ch?p=10 (有详细的视频过程演示和说明)
windows:shellcode生成框架和加载的更多相关文章
- shellcode生成框架
因为vs编译后自己会生成很多东西,我们稍微配置下 先获取kernel32基址 __declspec(naked) DWORD getKernel32() { __asm { mov eax, fs:[ ...
- ionic 在windows环境下更换logo和加载图片的问题
做用自己的电脑做ionic项目时,更换logo和加载图片时,无论使用哪种命令,发现都上传不了,并且报错 最后发现,需要将 icon和splash两个文件改为.ai格式才能上传成功. 这是最终生成后的文 ...
- 背水一战 Windows 10 (62) - 控件(媒体类): InkCanvas 保存和加载, 手写识别
[源码下载] 背水一战 Windows 10 (62) - 控件(媒体类): InkCanvas 保存和加载, 手写识别 作者:webabcd 介绍背水一战 Windows 10 之 控件(媒体类) ...
- Keras框架下的保存模型和加载模型
在Keras框架下训练深度学习模型时,一般思路是在训练环境下训练出模型,然后拿训练好的模型(即保存模型相应信息的文件)到生产环境下去部署.在训练过程中我们可能会遇到以下情况: 需要运行很长时间的程序在 ...
- 关于C# 窗体自动隐藏和加载的问题
最近在写一个小项目,开发一个小程序配合其他软件使用,其中一款软件在使用工作时需要截图生成报告,此时不能有其他应用程式界面在显示器桌面显示,故需要自动隐藏和加载窗体,通过阅读Windows API实现了 ...
- 前端性能和加载体验优化实践(附:PWA、离线包、内存优化、预渲染)
一.背景:页面为何会卡? 1.1 等待时间长(性能) 项目本身包/第三方脚本比较大. JavaScript 执行阻塞页面加载. 图片体积大且多. 特别是对于首屏资源加载中的白屏时间,用户等待的时间就越 ...
- linux 编译,链接和加载
1. 序 最近在折腾各种.so,碰到了一些问题,一开始对于很多错误也没有头绪,茫然不知所措.索性化了一天多时间将<<程序员的自我修养—链接.装载与库>>中部分内容略读了一遍 ...
- EF如何操作内存中的数据和加载外键数据:延迟加载、贪婪加载、显示加载
EF如何操作内存中的数据和加载外键数据:延迟加载.贪婪加载.显示加载 之前的EF Code First系列讲了那么多如何配置实体和数据库表的关系,显然配置只是辅助,使用EF操作数据库才是每天开发中都需 ...
- CLR查找和加载程序集的方式
C#开发者在开发WinForm程序.Asp.Net Web(MVC)程序等,不可避免的在项目中引用许多第三方的DLL程序集, 编译后引用的dll都放在根目录下.以我个人作品 AutoProject S ...
随机推荐
- IBM & Howdoo – 区块链上的智能社交
原文链接:https://www.themsphub.com/ibm-howdoo-smart-social-on-the-blockchain 我们很高兴地宣布,我们成为了一个令人兴奋的新社交网络的 ...
- display:inline-block 什么时候不会显示间隙?
移除空格 使用margin负值 使用font-size:0 letter-spacing word-spacing
- 03 Django模型层: 常用(非常用)字段和参数
Django模型层: 常用(非常用)字段和参数 1 ORM字段 AutoField int自增列,必须填入参数 primary_key=True.当model中如果没有自增列,则自动会创建一个列名为i ...
- 数据可视化基础专题(十二):Matplotlib 基础(四)常用图表(二)气泡图、堆叠图、雷达图、饼图、
1 气泡图 气泡图和上面的散点图非常类似,只是点的大小不一样,而且是通过参数 s 来进行控制的,多的不说,还是看个示例: 例子一: import matplotlib.pyplot as plt im ...
- .NET Core 微服务—API网关(Ocelot) 教程 [一]
前言: 最近在关注微服务,在 eShop On Containers 项目中存在一个API网关项目,引起想深入了解下它的兴趣. 一.API网关是什么 API网关是微服务架构中的唯一入口,它提供一个单独 ...
- 美国数学家维纳(N.Wiener)智力早熟,11岁就上了大学。他曾在1935~1936年应邀来中国清华大学讲学。 一次,他参加某个重要会议,年轻的脸孔引人注目。于是有人询问他的年龄,他回答说:我年龄的立方是个4位数。 我年龄的4次方是个6位数。这10个数字正好包含了从0到9这10个数字,每个都恰好出现1次。” 请你推算一下,他当时到底有多年轻。 结果只有一个数。
#include<stdio.h>int main(){ int age=1; int san=0; int si=0; int sum=0; while(age>0) { san= ...
- Kite: 一个分布式微服务框架(翻译)
原文链接:https://blog.gopheracademy.com/birthday-bash-2014/kite-microservice-library/ 此为中文翻译 用GO语言来编写web ...
- Python Ethical Hacking - VULNERABILITY SCANNER(7)
VULNERABILITY_SCANNER How to discover a vulnerability in a web application? 1. Go into every possibl ...
- 使用数据泵(expdp、impdp)迁移数据库流程
转载原文地址为:http://blog.itpub.net/26736162/viewspace-2652256/ 使用数据泵迁移数据库流程 How To Move Or Copy A Databas ...
- [开源硬件DIY] 自制一款精致炫酷的蓝牙土壤温湿度传感器,用于做盆栽呵护类产品(API开放,开发者可自行DIY微信小程序\安卓IOS应用)
目录 前言: 1. 成品展示 2. 原理图解析 3. pcb设计 4. 嵌入式对外提供接口 4.1 蓝牙广播 4.2 蓝牙服务和属性 4.3 数据包格式 4.4 数据通信模型 重要 . 前言: 本期给 ...