Rev/Write-up
HTB - debugme.exe
zooonique
2021. 1. 13. 20:01
반응형
```c
// positive sp value has been detected, the output may be wrong!
char mainCRTStartup_0()
{
int v0; // eax
unsigned __int64 v1; // rax
int v2; // ebx
unsigned __int64 v3; // rax
int (__cdecl *v4)(int, const char **, const char **); // eax
LOBYTE(v0) = NtCurrentPeb()->BeingDebugged;
if ( !(_BYTE)v0 )
{
LOBYTE(v0) = NtCurrentPeb()->UnicodeCaseTableData;
if ( !(_BYTE)v0 )
{
v1 = __rdtsc();
v2 = v1;
v3 = __rdtsc();
v0 = v3 - v2;
if ( v0 <= 1000 )
{
v4 = main;
do
{
*(_BYTE *)v4 ^= 0x5Cu;
v4 = (int (__cdecl *)(int, const char **, const char **))((char *)v4 + 1);
}
while ( (int)v4 <= (int)sub_401791 );
mingw_app_type = 0;
__security_init_cookie();
LOBYTE(v0) = __tmainCRTStartup();
}
}
}
return v0;
}
```
BeingDebugged와 UnicodeCaseTableData 부분이 안티디버깅함수이므로 이부분에 들어가면 안된다.
일단 BeingDebugged에 bp를 걸고, ctrl+n으로 main을 xor하는 부분으로 eip를 컨트롤한다.
그 후, xor된 main부분으로 가서 55라는 OPCODE부터 subroutine까지 드래그한후,
Analyze selected area를 처리를 해준다. xor된 main이 어셈블리의 형태로 재해석되고,
그 이후에 함수의 push ebp부분에서 P단축어를 이용해 패킹해주면 main함수를 디컴파일할수있다.
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned __int64 v3; // rax
int v4; // ebx
unsigned __int64 v5; // rax
int result; // eax
_BYTE *v7; // esi
_BYTE *v8; // edi
int v9; // ecx
_DWORD v10[10]; // [esp-28h] [ebp-28h] BYREF
if ( NtCurrentPeb()->BeingDebugged )
return printf("Looks like your doing something naughty. Stop it!!!\n");
if ( LOBYTE(NtCurrentPeb()->UnicodeCaseTableData) )
return printf("Looks like your doing something naughty. Stop it!!!\n");
v3 = __rdtsc();
v4 = v3;
v5 = __rdtsc();
if ( (int)v5 - v4 > 1000 )
return printf("Looks like your doing something naughty. Stop it!!!\n");
printf("I heard you like bugs so I put bugs in your debugger so you can have bugs while you debug!!!\n");
printf("Seriously though try and find the flag, you will find it in your debugger!!!\n");
v10[9] = 0x6A253E2D;
v10[8] = 0x14191431;
v10[7] = 0x20282239;
v10[6] = 0x3F14192E;
v10[5] = 0xC0C3E29;
v10[4] = 0x780F147A;
v10[3] = 0x3F250A14;
v10[2] = 0x2C252227;
v10[1] = 0x277B391F;
v7 = v10;
v8 = v10;
v9 = 36;
result = 0;
v10[0] = 0;
do
{
LOBYTE(result) = *v7++;
result ^= 0x4Bu;
*v8++ = result;
--v9;
}
while ( v9 );
return result;
}
메인함수는 위와같은데, v10에 어떤 문자열들을 넣고 이를 통해 연산작업을 거친다.
앞선과정과 동일하게 안티디버깅을 우회할 수 있게 EIP를 컨트롤한다.
v10에 문자열을 넣어주는 부분부터 xor하는 부분까지!
여기서 내가 실수한 부분은 eip를 컨트롤하는과정에서
어셈블리어 코드상으로 컨트롤하는게 더 정확하게 컨트롤을 할 수있다.
난 수도코드상에서만 컨트롤하다보니...자꾸 이상한 짓을 했다.
그러고 나면 v8에 플래그가 있다.
Tr0ling_Ant1_d3buGGeR_trickz_R_fun!
반응형