ソースはこちら https://azurda.github.io/posts/lpinternet_buffersa_struct_parse/
この記事では、Windows APIのHttpSendRequestExAで使用されるLPINTERNET_BUFFERSA
構造体の読み方について説明します。この投稿の背景には、StackOverflowの質問への回答があります。
この例では、アプリケーションを書く代わりにInternet Explorerを使用し、その上でFRIDAを使用しています。さて、HttpSendRequestExA/Wで使われている構造体の定義は以下の通りです。
typedef struct _INTERNET_BUFFERSA {
DWORD dwStructSize;
構造体_INTERNET_BUFFERSA *Next;
LPCSTR lpcszHeader;
DWORD dwHeadersLength;
DWORD dwHeadersTotal
LPVOID lpvBuffer;
DWORD dwBufferLength; DWORD dwBufferTotal; LPVOID lpvBuffer; DWORD dwBufferLength
DWORD dwBufferTotal; DWORD dwBufferLength; DWORD dwBufferTotal
DWORD dwOffsetLow;
DWORD dwOffsetHigh。
} internet_buffersa, *lpinternet_buffersa;
ここで注意すべき点は2つあります。1つ目は、最初のメンバーが構造体のサイズで、構造体の2つ目のメンバーが次の構造体へのポインタであることです。2つ目の注意点は、HttpSendRequestExW
の代わりにLPCSTR
を使うと、LPCWSTR
になってしまうことです。
とはいえ、この構造体を解析するのはとても簡単で、ここには厄介なメンバーが3つだけあります。
- LPCSTRのサイズは、
Process.pointerSize()
に依存して変化します。 - LPVOID サイズは
Process.pointerSize()
に応じて変化します。 *Next
は次の構造体へのポインタなので、Process.pointerSize()
に応じて変化します。
これを念頭に置いて、Process.pointerSize=4
の32ビットプロセスの場合、オフセットは以下のようになります。
DWORD dwStructSize; // 0
struct _INTERNET_BUFFERSA *Next; // 4
LPCSTR lpcszHeader; // 8
DWORD dwHeadersLength; // 12
DWORD dwHeadersTotal; // 16
LPVOID lpvBuffer; // 20
DWORD dwBufferLength; // 24
DWORD dwBufferTotal; // 28
DWORD dwOffsetLow; // 32
DWORD dwOffsetHigh; // 36
計算が正しければ、dwStructSizeは32ビットプロセスの場合は40、16進数では0x28
となります。以下のスクリプトは、32ビットプロセスのHttpSendRequestW構造体を正しくインターセプトすることができます。
Interceptor.attach(Module.getExportByName(null, "HttpSendRequestExW"), {)
onEnter (args) {
let internetBufferStruct = args[1];
console.log("Struct size: " + internetBufferStruct.readPointer())を実行します。
console.log("*Next: " + internetBufferStruct.add(Process.pointerSize).readPointer())を実行します。
console.log("lpcszHeader: " + internetBufferStruct.add(Process.pointerSize * 2).readPointer()) を実行します。
console.log("dwHeadersLength: " + internetBufferStruct.add(12).readPointer()) を実行します。
console.log("dwHeadersTotal: " + internetBufferStruct.add(16).readPointer());
let dwBufferLength = parseInt(internetBufferStruct.add(24).readPointer());
console.log("lpvBuffer: " + internetBufferStruct.add(Process.pointerSize * 5).readCString(dwBufferLength)) を実行します。
console.log("dwBufferLength: " + dwBufferLength");
console.log("dwBufferTotal: " + internetBufferStruct.add(28).readPointer());
console.log("dwOffsetLow: " + internetBufferStruct.add(32).readPointer());
console.log("dwOffsetHigh: " + internetBufferStruct.add(36).readPointer());
}
});
そして、これが32bitプロセスでの結果です。予測通り、最初のメンバーであるdwStructSize
は40(0x28)となりました。
64ビットプロセスでは、すべての pointer
メンバーが生成するオフセットの違いだけを変更し、それに応じて他のメンバーを調整する必要があります。
0 件のコメント:
コメントを投稿