golang怎么实现peb
时间:2023-04-15 04:48
PEB(Process Environment Block)是一个进程的环境块,其中保存了许多系统级别的信息,如进程的基地址、进程的环境变量、进程的命令行参数等。在Windows内核中,PEB被实现成了一个结构体,可以在Kernel Mode中通过Undocumented Native API(如ZwQueryInformationProcess)读取。 在本篇文章中,我们将介绍如何使用golang语言实现一个简单的PEB查看器。 获取当前进程的句柄。 在golang中,我们可以使用syscall包中的GetCurrentProcess函数来获取当前进程的句柄。 查询当前进程的信息,包括PEB的地址。 在Windows中,我们可以使用ZwQueryInformationProcess或者NtQueryInformationProcess来读取进程信息。不过,在golang中这些API并没有直接暴露出来,因此我们需要使用unsafe包来调用系统函数。 在上面的代码中,我们定义了一个PROCESS_BASIC_INFORMATION结构体,用来保存NtQueryInformationProcess函数返回的进程信息。我们通过指定PROCESS_BASIC_INFORMATION_CLASS枚举值来告诉系统我们需要读取的信息,这里我们需要的是PEB信息。另外,我们还需要提供一个缓冲区来保存返回的信息,和这个缓冲区的大小。 具体的实现可以参考这个项目[https://github.com/processhacker/phnt](https://github.com/processhacker/phnt),它实现了一些系统API,并且提供了一些数据结构,比如PROCESS_BASIC_INFORMATION。 读取PEB结构体中的信息。 PEB是一个非常重要的结构体,其中保存了许多进程的信息。下面是PEB的定义: 我们可以使用golang的unsafe包来读取这些数据。比如,我们可以使用下面的代码来读取PEB的ImageBaseAddress: 在上面的代码中,我们首先定义了一个PEB结构体,并且给结构体中的字段都指定了类型。接着,我们实现了一个GetImageBaseAddress函数,用来返回PEB中的ImageBaseAddress字段。最后,我们通过将PEB的基地址转换为*PEB类型,来读取PEB中的信息。 读取进程的模块信息。 在获取了PEB中的ImageBaseAddress后,我们可以遍历PEB_LDR_DATA中的InMemoryOrderModuleList来获取进程中加载的所有模块信息。 我们可以使用如下的代码来遍历模块信息: 在上面的代码中,我们首先定义了一个LDR_DATA_TABLE_ENTRY结构体,用来保存模块的信息。然后我们定义了一个PEB_LDR_DATA结构体,并且将peb.Ldr指针转换为这个结构体指针。最后,我们遍历InMemoryOrderModuleList链表,对每个模块进行读取操作。 在获取到模块的基地址后,我们可以用ReadProcessMemory函数来读取模块中的数据。具体的实现可以参考这个项目[https://github.com/AllenDang/w32/blob/master/process_windows.go](https://github.com/AllenDang/w32/blob/master/process_windows.go),它实现了从进程中读取数据的函数。 不过需要注意的是,如果我们要获取的进程是另外一个进程,那么在读取进程数据的时候需要指定进程的访问权限。在golang中,我们可以使用CreateToolhelp32Snapshot函数来获取所有进程列表,并且在获取进程句柄时指定具体的访问权限。 本文介绍了如何使用golang语言实现一个简单的PEB查看器。PEB是进程环境块,在Windows内核中被实现成了一个结构体,其中保存了许多系统级别的信息。通过使用golang的unsafe包,我们可以读取进程的PEB信息和模块信息。不过需要注意的是,在读取另一个进程的PEB信息和模块信息时,需要指定访问权限。 以上就是golang怎么实现peb的详细内容,更多请关注Gxl网其它相关文章!读取PEB的步骤
handle, err := syscall.GetCurrentProcess()if err != nil { fmt.Println("获取当前进程句柄失败:", err) return}defer syscall.CloseHandle(handle)
var pbi PROCESS_BASIC_INFORMATIONvar returnLength uint32ntStatus := NtQueryInformationProcess( handle, PROCESS_BASIC_INFORMATION_CLASS, uintptr(unsafe.Pointer(&pbi)), uint32(unsafe.Sizeof(pbi)), uintptr(unsafe.Pointer(&returnLength)),)if ntStatus != STATUS_SUCCESS { fmt.Println("获取进程PEB信息失败:", ntStatus) return}
typedef struct _PEB { BOOLEAN InheritedAddressSpace; BOOLEAN ReadImageFileExecOptions; BOOLEAN BeingDebugged; BOOLEAN SpareBool; HANDLE Mutant; PVOID ImageBaseAddress; PPEB_LDR_DATA Ldr; PRTL_USER_PROCESS_PARAMETERS ProcessParameters; PVOID SubSystemData; PVOID ProcessHeap; PRTL_CRITICAL_SECTION FastPebLock; PVOID AtlThunkSListPtr; PVOID IFEOKey; PVOID CrossProcessFlags; PVOID UserSharedInfoPtr; ULONG SystemReserved[1]; ULONG AtlThunkSListPtr32; PVOID ApiSetMap;} PEB, *PPEB;
type PEB struct { InheritedAddressSpace bool ReadImageFileExecOptions bool BeingDebugged bool SpareBool bool Mutant syscall.Handle ImageBaseAddress uintptr Ldr *PEB_LDR_DATA ProcessParameters *RTL_USER_PROCESS_PARAMETERS SubSystemData uintptr ProcessHeap uintptr FastPebLock *RTL_CRITICAL_SECTION AtlThunkSListPtr uintptr IFEOKey uintptr CrossProcessFlags uintptr UserSharedInfoPtr uintptr SystemReserved [1]uint32 AtlThunkSListPtr32 uintptr ApiSetMap uintptr}func (p *PEB) GetImageBaseAddress() uintptr { return p.ImageBaseAddress}peb := (*PEB)(unsafe.Pointer(pbi.PebBaseAddress))fmt.Printf("ImageBaseAddress: 0x%x
", peb.GetImageBaseAddress())
typedef struct _LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderLinks; LIST_ENTRY InMemoryOrderLinks; LIST_ENTRY InInitializationOrderLinks; PVOID DllBase; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; USHORT LoadCount; USHORT TlsIndex; union { LIST_ENTRY HashLinks; struct { PVOID SectionPointer; ULONG CheckSum; }; }; union { ULONG TimeDateStamp; struct { PVOID LoadedImports; PVOID EntryPointActivationContext; }; };} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;typedef struct _PEB_LDR_DATA { ULONG Length; BOOLEAN Initialized; HANDLE SsHandle; LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; PVOID EntryInProgress; BOOLEAN ShutdownInProgress; HANDLE ShutdownThreadId;} PEB_LDR_DATA, *PPEB_LDR_DATA;
type LDR_DATA_TABLE_ENTRY struct { InLoadOrderLinks LIST_ENTRY InMemoryOrderLinks LIST_ENTRY InInitializationOrderLinks LIST_ENTRY DllBase uintptr EntryPoint uintptr SizeOfImage uint32 FullDllName UNICODE_STRING BaseDllName UNICODE_STRING Flags uint32 LoadCount uint16 TlsIndex uint16 HashLinks LIST_ENTRY TimeDateStamp uint32}type PEB_LDR_DATA struct { Length uint32 Initialized bool SsHandle syscall.Handle InLoadOrderModuleList LIST_ENTRY InMemoryOrderModuleList LIST_ENTRY InInitializationOrderModuleList LIST_ENTRY}pebLdrData := (*PEB_LDR_DATA)(unsafe.Pointer(peb.Ldr))moduleList := (*LIST_ENTRY)(unsafe.Pointer(&pebLdrData.InMemoryOrderModuleList))for moduleList.Flink != uintptr(unsafe.Pointer(&pebLdrData.InMemoryOrderModuleList)) { ldrDataTableEntry := (*LDR_DATA_TABLE_ENTRY)(unsafe.Pointer(moduleList.Flink)) moduleName := WcharPtrToString(ldrDataTableEntry.BaseDllName.Buffer, uint32(ldrDataTableEntry.BaseDllName.Length/2)) moduleBase := ldrDataTableEntry.DllBase moduleSize := ldrDataTableEntry.SizeOfImage moduleEntry := ldrDataTableEntry.EntryPoint moduleList = (*LIST_ENTRY)(unsafe.Pointer(moduleList.Flink)) fmt.Printf("模块名称:%s,基地址:%x,大小:%x,入口点:%x
", moduleName, moduleBase, moduleSize, moduleEntry)}
const ( PROCESS_QUERY_INFORMATION = 0x0400 PROCESS_VM_READ = 0x0010 PROCESS_VM_WRITE = 0x0020 PROCESS_VM_OPERATION = 0x0008 PROCESS_CREATE_THREAD = 0x0002 PROCESS_CREATE_PROCESS = 0x0080 PROCESS_TERMINATE = 0x0001 PROCESS_ALL_ACCESS = 0x1F0FFF TH32CS_SNAPPROCESS = 0x00000002)func openProcess(pid uint32) (handle syscall.Handle, err error) { handle, err = syscall.OpenProcess(PROCESS_VM_READ|PROCESS_QUERY_INFORMATION|PROCESS_VM_WRITE, false, pid) return}func main() { snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) defer syscall.CloseHandle(snapshot) var procEntry PROCESSENTRY32 procEntry.Size = uint32(unsafe.Sizeof(procEntry)) var ( handle syscall.Handle err error ) if Process32First(snapshot, &procEntry) { for { if strings.EqualFold(strings.ToLower(WcharPtrToString(procEntry.ExeFile[:])), "notepad.exe") { fmt.Printf("找到 notepad 进程,pid:%d
", procEntry.ProcessID) handle, err = openProcess(procEntry.ProcessID) if err != nil { fmt.Println("打开进程失败:", err) } } if !Process32Next(snapshot, &procEntry) { break } } }}
结语