
DLLから関数を隠蔽的かつリバースエンジニアリングしにくい方法でインポートするためのライブラリ
リバースエンジニアの作業をはるかに困難にする、シンプルで使いやすいヘッダーオンリーライブラリです。
LI_FN(OutputDebugStringA)("hello world");
LI_FN(VirtualProtect).in(LI_MODULE("kernel32.dll").cached());
LI_FN(function_pointer) -> lazy_functionLI_FN_DEF(function_type) -> lazy_functionLI_MODULE(module_name) -> lazy_modulesafe は、関数がタスクを正常に完了できない場合に、未定義動作が発生する代わりに 0 が返されることを示します。cached は、結果が最初の呼び出し時のみ計算され、その後再利用されることを示します。forwarded は、エクスポートフォワーディングが正しく解決されることを示します。lazy_module| function | safe | cached | |
|---|---|---|---|
| 指定されたモジュールを検索し、そのアドレスを返そうとします | |||
get<T = void*>() -> T |
:x: | :x: | |
safe<T = void*>() -> T |
:white_check_mark: | :x: | |
cached<T = void*>() -> T |
:x: | :white_check_mark: | |
safe_cached<T = void*>() -> T |
:white_check_mark: | :white_check_mark: | |
| 指定された LDR_DATA_TABLE_ENTRY ポインタを使用して、指定されたモジュールを検索しようとします | |||
in<T = void*, Ldr>(Ldr ldr_entry) -> T |
:white_check_mark: | :x: | |
in_cached<T = void*, Ldr>(Ldr ldr_entry) -> T |
:white_check_mark: | :white_check_mark: | |
lazy_function<F>| function | safe | cached | forwarded |
|---|---|---|---|
| 指定された引数を使用して、解決されたエクスポートを呼び出します | |||
operator()(...) -> result_of<F, ...> |
:x: | :x: | :x: |
| ロードされているすべてのモジュールでエクスポートを解決しようとし、関数アドレスを返します | |||
get<T = F>() -> T |
:x: | :x: | :x: |
safe<T = F>() -> T |
:white_check_mark: | :x: | :x: |
cached<T = F>() -> T |
:x: | :white_check_mark: | :x: |
safe_cached<T = F>() -> T |
:white_check_mark: | :white_check_mark: | :x: |
forwarded<T = F>() -> T |
:x: | :x: | :white_check_mark: |
forwarded_safe<T = F>() -> T |
:white_check_mark: | :x: | :white_check_mark: |
forwarded_cached<T = F>() -> T |
:x: | :white_check_mark: | :white_check_mark: |
forwarded_safe_cached<T = F>() -> T |
:white_check_mark: | :white_check_mark: | :white_check_mark: |
| 指定されたモジュールでエクスポートを解決しようとし、関数アドレスを返します | |||
in<T = F, A>(A module_address) -> T |
:x: | :x: | :x: |
in_safe<T = F, A>(A module_address) -> T |
:white_check_mark: | :x: | :x: |
in_cached<T = F, A>(A module_address) -> T |
:x: | :white_check_mark: | :x: |
in_safe_cached<T = F, A>(A module_address) -> T |
:white_check_mark: | :white_check_mark: | :x: |
ntdll でエクスポートを解決しようとし、関数アドレスを返します |
|||
nt<T = F>() -> T |
:x: | :x: | :x: |
nt_safe<T = F>() -> T |
:white_check_mark: | :x: | :x: |
nt_cached<T = F>() -> T |
:x: | :white_check_mark: | :x: |
nt_safe_cached<T = F>() -> T |
:white_check_mark: | :white_check_mark: | :x: |
#define | 効果 |
|---|---|
LAZY_IMPORTER_NO_FORCEINLINE | 強制インライン化を無効にします |
LAZY_IMPORTER_CASE_INSENSITIVE | 大文字小文字を区別しない比較を有効にします。フォワーディングされたエクスポートの解決に必要になる場合があります。 |
LAZY_IMPORTER_CACHE_OPERATOR_PARENS | lazy_function の operator() で get() の代わりに cached() を使用します |
LAZY_IMPORTER_RESOLVE_FORWARDED_EXPORTS | get() で forwarded() を使用します。警告: nt() と in() には適用されません。 |
LAZY_IMPORTER_HARDENED_MODULE_CHECKS | モジュール列挙に追加の健全性チェックを加えます。 |
LAZY_IMPORTER_NO_CPP_FORWARD | <utility> C++ ヘッダーへの依存を削除します。 |
for ( i = *(_QWORD **)(*(_QWORD *)(__readgsqword(0x60u) + 24) + 16i64); ; i = (_QWORD *)*i )
{
v1 = i[6];
v2 = *(unsigned int *)(*(signed int *)(v1 + 60) + v1 + 136);
v3 = (_DWORD *)(v2 + v1);
if ( v2 + v1 != v1 )
{
LODWORD(v4) = v3[6];
if ( (_DWORD)v4 )
break;
}
LABEL_8:
;
}
while ( 1 )
{
v4 = (unsigned int)(v4 - 1);
v5 = -2128831035;
v6 = (char *)(v1 + *(unsigned int *)((unsigned int)v3[8] + 4 * v4 + v1));
v7 = *v6;
v8 = (signed __int64)(v6 + 1);
if ( v7 )
{
do
{
++v8;
v5 = 16777619 * (v5 ^ v7);
v7 = *(_BYTE *)(v8 - 1);
}
while ( v7 );
if ( v5 == -973690651 )
break;
}
if ( !(_DWORD)v4 )
goto LABEL_8;
}
((void (__fastcall *)(const char *))(v1
+ *(unsigned int *)(v1
+ (unsigned int)v3[7]
+ 4i64 * *(unsigned __int16 *)(v1 + (unsigned int)v3[9] + 2 * v4))))("hello world");
私と私のプロジェクトを支援するために連絡をくださり、寄付をしてくださった方々に感謝いたします