一部の学術研究のために、DLLの内容をメモリから読み取ろうとしています。具体的には、NTDSA.DLLライブラリは、プログラミングエラーをシミュレートしてシステムを強制的に失敗させる特定の命令を変更するためのものです。この失敗は、将来の失敗を予測するための機械学習アルゴリズムを学習するために記録されます(これは、これまでに公開された研究seen hereを一般化する試みです)。Win API予期しないデータを返すDLLのベースアドレスのReadProcessMemory
私は、hereで説明されているプロセスを通じてlsass.exeプロセス(ターゲットDLLを読み込む)の仮想メモリのベースアドレスと考えています。次に、割り当てられたバッファを持つReadProcessMemoryを呼び出し、 'PROCESS_ALL_ACCESS'が設定されたOpenProcessを呼び出して取得したlsassへのハンドルを取得します。 ReadProcessMemoryは、エラーコード299を返し、0バイトの読み込み時間(部分読み取り)の80%を返します。私の前提は、私がアクセスしようとしている領域は、呼び出しが行われたときに使用されているということです。幸い、私は要求しているバイト数を返すことがあります。残念ながら、返されたデータは、System32ディレクトリの静的DLLと比較すると、ディスク上のデータと一致しません。
ReadProcessMemoryは私がそれを与えるアドレスで面白い何かをしていますか、または私の仮想アドレスが間違っていますか?そのDLLがメモリにロードされる場所を特定する別の方法はありますか?何かご意見は?どんな助けや提案も大歓迎です。コードの追加
:
// FaultInjection.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <psapi.h>
#include <string>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <io.h>
#include <tchar.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]) {
// Declarations
int pid = 0;
__int64* start_addr;
DWORD size_of_ntdsa;
DWORD aProcesses[1024], cbNeeded, cProcesses;
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
HMODULE hmods[1024];
unsigned int i;
// Get All pids
if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)){
cout << "Failed to get all PIDs: " << GetLastError() << endl;
return -1;
}
// Find pid for lsass.exe
cProcesses = cbNeeded/sizeof(DWORD);
for (i = 0; i < cProcesses; i++) {
if (aProcesses[i] != 0) {
HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i]);
if (hProc != NULL) {
HMODULE hMod;
DWORD cbNeededMod;
if (EnumProcessModules(hProc, &hMod, sizeof(hMod), &cbNeededMod)) {
GetModuleBaseName(hProc, hMod, szProcessName, sizeof(szProcessName)/sizeof(TCHAR));
}
if (wstring(szProcessName).find(L"lsass.exe") != string::npos) {
pid = aProcesses[i];
}
CloseHandle(hProc);
}
}
}
cout << "lsass pid: " << pid << endl;
HANDLE h_lsass = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (!h_lsass) {
cout << "Failed to open process (are you root?): " << GetLastError() << endl;
return -1;
}
// Get Process Image File Name
char filename[MAX_PATH];
if (GetProcessImageFileName(h_lsass, (LPTSTR)&filename, MAX_PATH) == 0) {
cout << "Failed to get image file name: " << GetLastError() << endl;
CloseHandle(h_lsass);
return -1;
}
// Enumerate modules within process
if (EnumProcessModules(h_lsass, hmods, sizeof(hmods), &cbNeeded)) {
for (i = 0; i < (cbNeeded/sizeof(HMODULE)); i++) {
TCHAR szModName[MAX_PATH];
if (GetModuleFileNameEx(h_lsass, hmods[i], szModName, sizeof(szModName)/sizeof(TCHAR))) {
if (wstring(szModName).find(L"NTDSA.dll") != string::npos) {
_tprintf(TEXT("%s\n"), szModName);
MODULEINFO lModInfo = { 0 };
if (GetModuleInformation(h_lsass, hmods[i], &lModInfo, sizeof(lModInfo))){
cout << "\t Base Addr: " << lModInfo.lpBaseOfDll << endl;
cout << "\t Entry Point: " << lModInfo.EntryPoint << endl;
cout << "\t Size of image: " << lModInfo.SizeOfImage << endl;
start_addr = (__int64*)lModInfo.lpBaseOfDll;
size_of_ntdsa = lModInfo.SizeOfImage;
}
else {
cout << "Failed to Print enumerated list of modules: " << GetLastError() << endl;
}
}
} else {
cout << "Failed to Print enumerated list of modules: " << GetLastError() << endl;
}
}
}
else {
cout << "Failed to enum the modules: " << GetLastError() << endl;
}
// Ready to continue?
string cont = "";
cout << "Continue? [Y|n]: ";
getline(cin, cont);
if (cont.find("n") != string::npos || cont.find("N") != string::npos) {
CloseHandle(h_lsass);
return 0;
}
void* buf = malloc(size_of_ntdsa);
if (!buf) {
cout << "Failed to allocate space for memory contents: " << GetLastError() << endl;
CloseHandle(h_lsass);
return -1;
}
SIZE_T num_bytes_read = 0;
int count = 0;
if (ReadProcessMemory(h_lsass, &start_addr, buf, size_of_ntdsa, &num_bytes_read) != 0) {
cout << "Read success. Got " << num_bytes_read << " bytes: " << endl;
} else {
int error_code = GetLastError();
if (error_code == 299) {
cout << "Partial read. Got " << num_bytes_read << " bytes: " << endl;
} else {
cout << "Failed to read memory: " << GetLastError() << endl;
CloseHandle(h_lsass);
free(buf);
return -1;
}
}
if (num_bytes_read > 0) {
FILE *fp;
fopen_s(&fp, "C:\\ntdsa_new.dll", "w");
SIZE_T bytes_written = 0;
while (bytes_written < num_bytes_read) {
bytes_written += fwrite(buf, 1, num_bytes_read, fp);
}
fclose(fp);
cout << "Wrote " << bytes_written << " bytes." << endl;
}
CloseHandle(h_lsass);
free(buf);
return 0;
}
理由がわかりません。 – paullj1
ReadProcessMemory()で(&)変数start_addrのアドレスを使用するのはなぜですか? – ssbssa
ええと...私はC/C++を書いて以来ずっと長くなっていたので、それが問題でした。どのくらい私が目の2番目のセットに感謝するかは分かりません。 – paullj1