2021年7月12日月曜日

FRIDAでC++のstd::string

私たちにとって非常に興味深いのは、文字列を読み取る機能です。しかし、文字列の表現方法が異なるため、FRIDAのreadUtf8String/readCString組み込み関数を使用するだけでは、文字列を読み取ることができない場合があります。例えば、WindowsのUNICODE_STRINGは構造体で次のように定義されています。
 typedef struct _UNICODE_STRING {  
  USHORT Length;  
  USHORT MaximumLength;  
  PWSTR Buffer;  
 } UNICODE_STRING, *PUNICODE_STRING;  
パースする一般的な文字列型は、C++のstd::stringです。同様の概念は、後にSwift.Stringのデータ型でも見られます。std::stringのLSB(Least Significant Bit)には、短い文字列(22バイト以下)の場合は0が、長い文字列の場合は1が格納されます。長い文字列の場合、取得したい文字列へのポインタは、接続されているプロセスのProcess.pointerSizeの2倍の値が格納されます。この知識を試して、文字列を取得する方法を確認するために、この簡単なプログラムを見てみましょう。
 #include <iostream>  
 void print_std_string(std::string arg_1)  
 {  
      std::cout << arg_1 << std::endl;  
 }  
 int  
 main(void)  
 {  
      std::string my_string = "FRIDA is great, you should check it out at frida.re";  
      print_std_string(my_string);  
      return 0;  
 }  
このプログラムは、単にprint_std_string(std::string arg_1)関数を呼び出して、画面に表示しているだけです。このようにして、std::stringのパラメータを取得し、検査することが簡単にできます。FRIDAのREPLでこのプログラムを起動し、バイナリ上でModule.enumerateExportsSync()を実行すると、名前がつぶれていることに気づきます。しかし、テスト関数に選んだ名前のおかげで、_Z16print_std_stringNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEという名前のつぶれた関数を見つけることができます。これが、Interceptor.attachを使用したい関数です。
 Interceptor.attach(Module.getExportByName(null, '_Z16print_std_stringNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE'), {  
      onEnter (args) {  
           const LSB = args[0].readU8() & 1;  
           console.log('LSB: ' + LSB);  
           const stdString = args[0].add(Process.pointerSize*2).readPointer().readUtf8String();  
           console.log("std::string: " + stdString);  
      }  
 });  
そして、この小さなスクリプトを実行すると、次のような出力が得られます。 

 LSB: 1 std::string: FRIDA is great, you should check it out at frida.re 
[Local::a.out]-> Process terminated 

このテストはclang++ 12.0.0を使用して行われており、小さな文字列を格納するためにユニオンを実装しているGCCなどのコンパイラでは、メモリのレイアウトが異なる可能性があることに留意する必要があります。

0 件のコメント:

コメントを投稿

FRIDAでHTTPSENDREQUESTEXのLPINTERNET_BUFFERSA構造体の解析

ソースはこちら https://azurda.github.io/posts/lpinternet_buffersa_struct_parse/