初识Go逆向


 工具参考:

 https://github.com/goretk/redress

https://github.com/0xjiayu/go_parser

一、先写一个程序

package main

import "fmt"

func main() {
   fmt.Println("Hello, World!")
}

编译,定位到文件目录

C:\Go_WorkSpace>go build

IDA查看main_main函数中看着没有相关信息

直接查看字符串没有"Hello, World!"

使用go_parser插件就可以在字符串窗口看到我们的"Hello, World!"

查看汇编代码,直接通过堆栈赋值传递,并且IDA解析没有解析到这个参数

 去符号编译后,IDA函数都不识别了

go build -ldflags="-s -w"

使用go_parse后,可以找到“hello, world!”字符串以及函数识别

二、实战下go实现注入

参考

w32

go-win32-inject-tool

package main

import (
    "syscall"
    "unsafe"
    "unicode/utf16"
)

import "fmt"

type (
    HANDLE uintptr
    BOOL int32
)

var (
    modadvapi32               = syscall.NewLazyDLL("advapi32.dll")
)

const (
    ProcessAllAccess = 0x2035711
)


var (
    modkernel32, _            = syscall.LoadDLL("kernel32.dll")
    procCreateRemoteThread, _ = modkernel32.FindProc("CreateRemoteThread")
    procGetModuleHandleA, _   = modkernel32.FindProc("GetModuleHandleA")
    procCopyMemory, _                 = modkernel32.FindProc("RtlCopyMemory")
    procCloseHandle, _               = modkernel32.FindProc("CloseHandle")
    procConnectNamedPipe, _           = modkernel32.FindProc("ConnectNamedPipe")
    procCreateFileW, _                = modkernel32.FindProc("CreateFileW")
    procCreateNamedPipeW, _           = modkernel32.FindProc("CreateNamedPipeW")
    procCreateProcessA, _             = modkernel32.FindProc("CreateProcessA")
    procCreateProcessW, _             = modkernel32.FindProc("CreateProcessW")
    procCreateToolhelp32Snapshot, _   = modkernel32.FindProc("CreateToolhelp32Snapshot")
    procFindResource, _               = modkernel32.FindProc("FindResourceW")
    procGetConsoleScreenBufferInfo, _ = modkernel32.FindProc("GetConsoleScreenBufferInfo")
    procGetConsoleWindow, _           = modkernel32.FindProc("GetConsoleWindow")
    procGetCurrentThread, _           = modkernel32.FindProc("GetCurrentThread")
    procGetDiskFreeSpaceEx, _         = modkernel32.FindProc("GetDiskFreeSpaceExW")
    procGetExitCodeProcess, _         = modkernel32.FindProc("GetExitCodeProcess")
    procGetLastError , _              = modkernel32.FindProc("GetLastError")
    procGetLogicalDrives, _           = modkernel32.FindProc("GetLogicalDrives")
    procGetModuleHandle , _           = modkernel32.FindProc("GetModuleHandleW")
    procGetProcAddress , _            = modkernel32.FindProc("GetProcAddress")
    procGetProcessTimes, _            = modkernel32.FindProc("GetProcessTimes")
    procGetSystemTime, _              = modkernel32.FindProc("GetSystemTime")
    procGetSystemTimes, _             = modkernel32.FindProc("GetSystemTimes")
    procGetSystemInfo  , _            = modkernel32.FindProc("GetSystemInfo")
    procGetUserDefaultLCID, _         = modkernel32.FindProc("GetUserDefaultLCID")
    procGlobalAlloc, _                = modkernel32.FindProc("GlobalAlloc")
    procGlobalFree , _                = modkernel32.FindProc("GlobalFree")
    procGlobalLock , _                = modkernel32.FindProc("GlobalLock")
    procGlobalUnlock, _               = modkernel32.FindProc("GlobalUnlock")
    procLoadLibraryA, _               = modkernel32.FindProc("LoadLibraryA")
    procLoadResource, _               = modkernel32.FindProc("LoadResource")
    procLockResource, _               = modkernel32.FindProc("LockResource")
    procLstrcpy , _                   = modkernel32.FindProc("lstrcpyW")
    procLstrlen , _                   = modkernel32.FindProc("lstrlenW")
    procProcess32First, _             = modkernel32.FindProc("Process32FirstW")
    procProcess32Next, _              = modkernel32.FindProc("Process32NextW")
    procModule32First, _             = modkernel32.FindProc("Module32FirstW")
    procModule32Next , _              = modkernel32.FindProc("Module32NextW")
    procMoveMemory , _                = modkernel32.FindProc("RtlMoveMemory")
    procMulDiv, _                     = modkernel32.FindProc("MulDiv")
    procOpenProcess  , _              = modkernel32.FindProc("OpenProcess")
    procQueryPerformanceCounter , _   = modkernel32.FindProc("QueryPerformanceCounter")
    procQueryPerformanceFrequency , _ = modkernel32.FindProc("QueryPerformanceFrequency")
    procReadProcessMemory, _          = modkernel32.FindProc("ReadProcessMemory")
    procSetConsoleCtrlHandler, _      = modkernel32.FindProc("SetConsoleCtrlHandler")
    procSetConsoleTextAttribute, _    = modkernel32.FindProc("SetConsoleTextAttribute")
    procSetSystemTime   , _           = modkernel32.FindProc("SetSystemTime")
    procSizeofResource , _            = modkernel32.FindProc("SizeofResource")
    procTerminateProcess, _           = modkernel32.FindProc("TerminateProcess")
    procVirtualAlloc  , _             = modkernel32.FindProc("VirtualAlloc")
    procVirtualAllocEx , _            = modkernel32.FindProc("VirtualAllocEx")
    procVirtualFreeEx , _             = modkernel32.FindProc("VirtualFreeEx")
    procVirtualProtect, _             = modkernel32.FindProc("VirtualProtect")
    procVirtualQuery  , _             = modkernel32.FindProc("VirtualQuery")
    procVirtualQueryEx, _             = modkernel32.FindProc("VirtualQueryEx")
    procWaitForSingleObject, _        = modkernel32.FindProc("WaitForSingleObject")
    procWriteFile    , _              = modkernel32.FindProc("WriteFile")
    procWriteProcessMemory  , _       = modkernel32.FindProc("WriteProcessMemory")

    procResumeThread, _  = modkernel32.FindProc("ResumeThread")
    procSuspendThread, _ = modkernel32.FindProc("SuspendThread")
)

func IsErrSuccess(err error) bool {
    if errno, ok := err.(syscall.Errno); ok {
        if errno == 0 {
            return true
        }
    }
    return false
}

func ReadProcessMemory(hProcess HANDLE, lpBaseAddress uint32, size uint) (data []byte, err error) {
    var numBytesRead uintptr
    data = make([]byte, size)

    _, _, err = procReadProcessMemory.Call(uintptr(hProcess),
        uintptr(lpBaseAddress),
        uintptr(unsafe.Pointer(&data[0])),
        uintptr(size),
        uintptr(unsafe.Pointer(&numBytesRead)))
    if !IsErrSuccess(err) {
        return
    }
    err = nil
    return
}

func UTF16PtrToString(cstr *uint16) string {
    if cstr != nil {
        us := make([]uint16, 0, 256)
        for p := uintptr(unsafe.Pointer(cstr)); ; p += 2 {
            u := *(*uint16)(unsafe.Pointer(p))
            if u == 0 {
                return string(utf16.Decode(us))
            }
            us = append(us, u)
        }
    }

    return ""
}

func GetPrivileges() {
    var token syscall.Token
    handle, _ := syscall.GetCurrentProcess()
    //失败
    if nil != syscall.OpenProcessToken(handle, syscall.TOKEN_ALL_ACCESS, &token) {
        return
    }
    //    syscall.Syscall(procLookupPrivilegeValueW.Addr(),nil,)
}

type Process struct {
    ProcessID int
    Name      string
    Exe       string
}

//获取进程的名字
func GetProcessesByName(exeFile string) (*Process, string) {
    handle, _ := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0)
    if handle == 0 {
        return nil, "创建Snapshot失败"
    }
    defer syscall.CloseHandle(handle)

    //定义句柄存储
    var entry = syscall.ProcessEntry32{}
    entry.Size = uint32(unsafe.Sizeof(entry))
    var process Process
    //定义一个实体类型
    for true {
        if nil != syscall.Process32Next(handle, &entry) {
            break
        }
        //执行文件的名称
        _exeFile := UTF16PtrToString(&entry.ExeFile[0])
        if exeFile == _exeFile {
            process.Name = _exeFile
            process.ProcessID = int(entry.ProcessID)
            process.Exe = _exeFile
            return &process, ""
        }

    }
    return nil, "未找到进程"
}


func GetModuleHandleA(name string) (r1 uintptr, err error) {
    bytes := []byte(name)
    r1, _, err = procGetModuleHandleA.Call(uintptr(unsafe.Pointer(&bytes[0])))
    err = syscall.GetLastError()
    return
}

func GetLoadLibraryAAddr() (uintptr, error) {
    handle, err := GetModuleHandleA("Kernel32.dll")
    if err != nil {
        return 0, err
    }
    ptr, err := syscall.GetProcAddress(syscall.Handle(handle), "LoadLibraryA")
    err = syscall.GetLastError()
    return ptr, err
}

//分配虚拟内存
func VirtualAllocEx(hwnd syscall.Handle, lpaddress uint32, size uint32, tp uint32, tect uint32) (r1 uintptr, err error) {
    r1, _, _ = procVirtualAllocEx.Call(uintptr(hwnd), uintptr(lpaddress), uintptr(size), uintptr(tp), uintptr(tect), 0)
    err = syscall.GetLastError()
    return
}

func WriteProcessMemory(hwnd syscall.Handle, addr uint32, lpBuffer uintptr, nsize uint32, filewriten uint32) (r1 uintptr, err error) {
    r1, _, err = procWriteProcessMemory.Call(uintptr(hwnd), uintptr(addr), lpBuffer, uintptr(nsize), uintptr(filewriten), 0)
    err = syscall.GetLastError()
    return
}

//执行远程线程调用方法
func CreateRemoteThread(hwnd syscall.Handle, threadAttributes uint32, stackSize uint32, startAddress uintptr, parameter uintptr, creationFlags uint32, threadid uint32) (r1 uintptr, err error) {
    r1, _, err = procCreateRemoteThread.Call(uintptr(hwnd), uintptr(threadAttributes), uintptr(stackSize), uintptr(startAddress), uintptr(parameter), uintptr(creationFlags), uintptr(threadid))
    err = syscall.GetLastError()
    return
}


func Inject(name string, dll string) string {
    //1.获取微信的进程ID
    process, err := GetProcessesByName(name)
    if err != "" {
        return err
    }

    //2.打开进程
    handle, ex := syscall.OpenProcess(uint32(ProcessAllAccess), false, uint32(process.ProcessID))
    if ex != nil {
        return "打开进程失败"
    }
    defer syscall.CloseHandle(handle)
    var dllLength = len(dll) + 1
    //3.分配虚拟内存,写入dll名字路径
    dllMemAddr, ex := VirtualAllocEx(handle, 0, uint32(dllLength), 4096, 4)
    if ex != nil {
        return "分配内存失败"
    }
    bt := []byte(dll)
    //4.写入内存
    _, ex = WriteProcessMemory(handle, uint32(dllMemAddr), uintptr(unsafe.Pointer(&bt[0])), uint32(dllLength), 0)
    if ex != nil {
        return "写入内存失败"
    }

    //5.测试一下读出内存
    bytes, _ := ReadProcessMemory(HANDLE(handle), uint32(dllMemAddr), uint(dllLength))
    fmt.Println("开始加载DLL:", string(bytes[:]))

    //5.远程执行
    loadAddr, ex := GetLoadLibraryAAddr()
    println(loadAddr)
    if ex != nil {
        return "获取内核地址失败"
    }
    pch, ex := CreateRemoteThread(handle, 0, 0, loadAddr, dllMemAddr, 0, 0)
    if ex != nil {
        println(ex)
        return "远程加载DLL失败:"
    }
    defer syscall.CloseHandle(syscall.Handle(pch))

    return "DLL注入成功"
}


func main() {
    dll := "C:\\Users\\Godtoy\\source\\repos\\WechatHookDemo1\\Debug\\GetWxInfo.dll"
    var wx = "WeChat.exe"
    err := Inject(wx, dll)
    println(err)
}

 

redress命令行: 

使用redress查看go结构体

 查看go的pkg

 查看go源码