次のようなコードがあると仮定しましょう。
unsigned char *bytes;
some_extremely_complicated_function_which_decrypt_key(bytes);
add_some_confusing_things();
maybe_even_split_into_several_calls(bytes);
// ...
call_function_using_their_key(bytes,data1,data2,data3);
これにより、アセンブラは次のようになります。
push [ebp+0004h] // data3
push ecx // data2
push [ebp+0024h] // data1
push [eax] // key (bytes)
call 123456h // call to call_function_using_their_key
ほとんどの場合、インポート/再配置テーブルからアドレスを取得できcall_function_using_their_key
ます(インライン、難読化、または同様の手法がほとんどない場合を除く)。
すべてにブレークポイントを自動的に追加しcall 123456h
、最後のプッシュ=キー、メモリアドレスを指すキー、543216h
からキーを取得します543216h
。
暗号化は役に立たなかった。
話の教訓:最初に、APIがデータを暗号化するのに意味があることを確認してください。そうしないと、これでうまくいくでしょう:
char *globalBytesPtr;
int main(){
globalBytesPtr = malloc(N);
globalBytesPtr[8] = 0x35;
globalBytesPtr[3] = 0x14;
globalBytesPtr[5] = 0x20;
...
}
これを使用すると、キーが静的ダンプに表示されないためです。最も弱い点はAPI呼び出しであり、このユニバースでアプリケーションをより安全にすることはできないため、これによってセキュリティが低下することはありません。