golangでpebを実装する方法
PEB (プロセス環境ブロック) はプロセスの環境ブロックであり、プロセスのベース アドレス、プロセスの環境変数、プロセスのコマンド ライン パラメーターなど、多くのシステム レベルの情報が保存されます。 、など。 Windows カーネルでは、PEB は構造として実装されており、カーネル モードで文書化されていないネイティブ API (ZwQueryInformationProcess など) を通じて読み取ることができます。
この記事では、golang 言語を使用して簡単な PEB ビューアを実装する方法を紹介します。
PEB を読む手順
-
現在のプロセスのハンドルを取得します。
golang では、syscall パッケージの GetCurrentProcess 関数を使用して、現在のプロセスのハンドルを取得できます。
handle, err := syscall.GetCurrentProcess() if err != nil { fmt.Println("获取当前进程句柄失败:", err) return } defer syscall.CloseHandle(handle)
ログイン後にコピー -
PEB のアドレスを含む、現在のプロセスの情報をクエリします。
Windows では、ZwQueryInformationProcess または NtQueryInformationProcess を使用してプロセス情報を読み取ることができます。ただし、これらの API は golang で直接公開されていないため、システム関数を呼び出すには安全でないパッケージを使用する必要があります。
var pbi PROCESS_BASIC_INFORMATION var returnLength uint32 ntStatus := 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 }
ログイン後にコピー上記のコードでは、NtQueryInformationProcess 関数によって返されたプロセス情報を保存するための PROCESS_BASIC_INFORMATION 構造体を定義します。 PROCESS_BASIC_INFORMATION_CLASS 列挙値を指定して、読み取る必要がある情報をシステムに伝えます。ここで必要なのは PEB 情報です。さらに、返された情報を保存するためのバッファーとこのバッファーのサイズも提供する必要があります。
具体的な実装については、このプロジェクト [https://github.com/processhacker/phnt](https://github.com/processhacker/phnt) を参照してください。このプロジェクトは、いくつかのシステム API を実装し、いくつかの機能を提供します。 PROCESS_BASIC_INFORMATION などのデータ構造。
-
PEB 構造内の情報を読みます。
PEB は、多くのプロセスに関する情報を保存する非常に重要な構造です。以下は PEB の定義です:
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;
ログイン後にコピーgolang の安全でないパッケージを使用してこれらのデータを読み取ることができます。たとえば、次のコードを使用して PEB の ImageBaseAddress を読み取ることができます。
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\n", peb.GetImageBaseAddress())
ログイン後にコピー上記のコードでは、最初に PEB 構造を定義し、構造内のフィールドの型を指定します。次に、PEB の ImageBaseAddress フィールドを返す GetImageBaseAddress 関数を実装しました。最後に、PEB のベース アドレスを *PEB タイプに変換することで、PEB 内の情報を読み取ります。
- #プロセスのモジュール情報を読み取ります。 PEB で ImageBaseAddress を取得した後、PEB_LDR_DATA の InMemoryOrderModuleList を走査して、プロセスにロードされたすべてのモジュール情報を取得できます。
次のコードを使用してモジュール情報をスキャンできます:
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;
ログイン後にコピー上記のコードでは、まず 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 関数を使用してすべてのプロセスのリストを取得し、プロセス ハンドルを取得するときに特定のアクセス許可を指定できます。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\n", 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\n", procEntry.ProcessID) handle, err = openProcess(procEntry.ProcessID) if err != nil { fmt.Println("打开进程失败:", err) } } if !Process32Next(snapshot, &procEntry) { break } } } }
ログイン後にコピー
以上がgolangでpebを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











GO言語は、効率的でスケーラブルなシステムの構築においてうまく機能します。その利点には次のものがあります。1。高性能:マシンコードにコンパイルされ、速度速度が速い。 2。同時プログラミング:ゴルチンとチャネルを介してマルチタスクを簡素化します。 3。シンプルさ:簡潔な構文、学習コストとメンテナンスコストの削減。 4。クロスプラットフォーム:クロスプラットフォームのコンパイル、簡単な展開をサポートします。

Golangは並行性がCよりも優れていますが、Cは生の速度ではGolangよりも優れています。 1)Golangは、GoroutineとChannelを通じて効率的な並行性を達成します。これは、多数の同時タスクの処理に適しています。 2)Cコンパイラの最適化と標準ライブラリを介して、極端な最適化を必要とするアプリケーションに適したハードウェアに近い高性能を提供します。

speed、効率、およびシンプル性をspeedsped.1)speed:gocompilesquilesquicklyandrunseffictient、理想的なlargeprojects.2)効率:等系dribribraryreducesexexternaldedenciess、開発効果を高める3)シンプルさ:

Golangは、パフォーマンスとスケーラビリティの点でPythonよりも優れています。 1)Golangのコンピレーションタイプの特性と効率的な並行性モデルにより、高い並行性シナリオでうまく機能します。 2)Pythonは解釈された言語として、ゆっくりと実行されますが、Cythonなどのツールを介してパフォーマンスを最適化できます。

GolangとPythonにはそれぞれ独自の利点があります。Golangは高性能と同時プログラミングに適していますが、PythonはデータサイエンスとWeb開発に適しています。 Golangは同時性モデルと効率的なパフォーマンスで知られていますが、Pythonは簡潔な構文とリッチライブラリエコシステムで知られています。

GolangとCのパフォーマンスの違いは、主にメモリ管理、コンピレーションの最適化、ランタイム効率に反映されています。 1)Golangのゴミ収集メカニズムは便利ですが、パフォーマンスに影響を与える可能性があります。

GolangとCにはそれぞれパフォーマンス競争において独自の利点があります。1)Golangは、高い並行性と迅速な発展に適しており、2)Cはより高いパフォーマンスと微細な制御を提供します。選択は、プロジェクトの要件とチームテクノロジースタックに基づいている必要があります。

Cは、ハードウェアリソースと高性能の最適化が必要なシナリオにより適していますが、Golangは迅速な開発と高い並行性処理が必要なシナリオにより適しています。 1.Cの利点は、ハードウェア特性と高い最適化機能に近いものにあります。これは、ゲーム開発などの高性能ニーズに適しています。 2.Golangの利点は、その簡潔な構文と自然な並行性サポートにあり、これは高い並行性サービス開発に適しています。
