僕の考えた解析され辛いデバッガー検出


#include <stdio.h>
#include <windows.h>

typedef BOOL(*IS_DEBUGGER_PRESENT)(void);

int debug_flag = -12;
IS_DEBUGGER_PRESENT proc;

void proc_set(){
	char name[] = "IrFffpa`m{Zyi~kad";
	int i,size=strlen(name);

	i = 0;
	while(i < size){
		name[i] ^= i;
		i++;
	}
	proc = (IS_DEBUGGER_PRESENT)GetProcAddress(GetModuleHandle("kernel32.dll"),name);
	memset(name,0,size);
}

void check(int n){
	debug_flag += proc()+1;
	if(n>0){
		check(n-1);
	}
}

main(){
	BYTE a[4];
	do{
		proc_set();
		check(8);
		*(int*)&a[3+debug_flag] = 0x12345678;
	}while(a[1]!=0x56);
	printf("ok");
	getchar();
	return 0;
}

前提知識:C言語全般、win32API基礎、IsDebuggerPresentはデバッガーを検出すると1を返す関数でkernel32.dllの中に含まれている事。

まず、procとdebug_flagをグローバル領域(動的ではなく固定割り当て)にする事で、探索必要領域を広げ見つけ辛くさせる。

GetProcAddress経由でIsDebuggerPresentのアドレスを取得する事で、使用している外部関数の列挙から逃れる。

GetProcAddress関数を呼ぶ際に使う”IsDebuggerPresent”文字列は暗号化した状態で保持し、なおかつ無駄な関数呼び出しをすることでデコード後もメモリーに残らなくする。
(暗号化が適当なのは仕様、一応書きやすいようASCII文字範囲から抜けないようにという意図がある)

IsDebuggerPresentを呼び出した前後では判定を行わない、なおかつflagを直接if文で使わず配列への代入位置とし間接的な判定を行うことで、万が一場所が割れても安易にif文を変更できないようにした。

デバッガー検出した場合に終了するのではなくループさせ続ける事で、判定箇所を特定し辛くした。
(オーバーフローの危険性があるが、むしろその方が解析ミスを疑わせられるためあえてこうしてある)

ちなみに、このデバッガー検出を突破する方法は、IsDebuggerPresent側を改造して常に0を返させればいいだけ。
解析改造とは常にイタチゴッコである。

コメントを残す

メールアドレスが公開されることはありません。