HackCTF static
2019. 7. 25. 02:34ㆍ0x02 Reverse Engineer/0x03. Etc
728x90
해당 문제 컨셉 : Binary Patch
환경 : 64bit ELF
Thinking.. static이 문제 명인 이유 : 도출 된 input 값을 입력하면 특정 문자에 의해 command가 먹히지 않음.
그래서 정적으로 분석하고 코드를 짜야함.
패치 하면 다음과 같은 코드를 볼 수 있음.
__int64 __fastcall sub_A3A(int argc, char **argv, char **a3)
{
const char *s1; // [rsp+20h] [rbp-10h]
// bi0s ~~
s1 = getenv("team_name");
if ( s1 && !strncmp(s1, "bi0s", 4uLL) ) //
//
{
if ( argc == 2 )
{
if ( (unsigned int)enc(s1, argv[1]) == 1 )
printFlag((__int64)argv[1]);
else
printf("Better luck next time!", argv);
}
else
{
printf("usage: chall <input>", "bi0s", argv);
}
}
else
{
printf("Nope.", argv);
}
return 0LL;
}
환경변수 안만들고도 진행할 수 있다 strncmp가 있기 때문에.
그럼 첫번째 if문 가볍게 우회한다고 가정하자.
enc 함수에 접근
__int64 __fastcall enc(const char *bi0s, const char *inputKey)
{
void *flag; // rdi
char v3; // dl
size_t newIndex; // rax
char *copyDummy; // [rsp+8h] [rbp-68h] 차이 : 8바이트
char v7[32]; // [rsp+10h] [rbp-60h] 32는 페이크야
__int64 realKEy; // [rsp+30h] [rbp-40h]
__int64 v9; // [rsp+38h] [rbp-38h]
int v10; // [rsp+40h] [rbp-30h]
__int16 v11; // [rsp+44h] [rbp-2Ch]
char v12; // [rsp+46h] [rbp-2Ah]
int v13; // [rsp+48h] [rbp-28h] 사용 안하는 값
int v14; // [rsp+4Ch] [rbp-24h]
int v15; // [rsp+50h] [rbp-20h] 사용 안하는 값
int index; // [rsp+54h] [rbp-1Ch]
int xorVal; // [rsp+58h] [rbp-18h]
int i; // [rsp+5Ch] [rbp-14h]
// real : 4919197161836291817161 이네
copyDummy = (char *)bi0s; // 22글자
xorVal = 0;
index = 0;
realKEy = '91817161'; // key
v9 = '71618362';
v10 = '1919';
v11 = '49';
v12 = 0;
flag = (void *)inputKey;
if ( strlen(inputKey) == 22 ) // input이 22글자되어야 하고 bi0s는 xor에 이용된다
{
for ( i = 0; i < strlen(copyDummy); ++i ) // 4
xorVal += copyDummy[i]; // bi0s
v13 = 0;
xorVal /= 30; // 후 처리
while ( index != 22 )
{
if ( index & 1 ) // 짝수 / 홀수
v3 = inputKey[index] - 4;
else
v3 = inputKey[index] + 4;
v7[index] = v3;
v7[index] ^= xorVal;
++index;
}
v15 = 0;
flag = v7;
for ( i = strlen(v7) - 1; i >= 0; --i ) // 22여야함
{
flag = v7;
newIndex = strlen(v7); // 길이 22
if ( v7[newIndex - i - 1] != *((_BYTE *)&realKEy + i) )
return nullsub_2(flag);
}
v14 = 0;
}
return nullsub_2(flag);
}
*((_BYTE*)&realKey+i)) 의 의미를 알아야 함 .
위의 코드를 통해 페이로드를 작성하면 다음과 같다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
// round 1
int main()
{
char env[5] = "bi0s";
char xorVal = 0;
char inputKey[23] = "\0";
char realKey[23] = "4919197161836291817161";
char v7[] = "\0";
int index = 0;
char v3;
// 2단계
for (int i = 0; i < strlen(realKey); i++)
{
inputKey[i] = realKey[i] ^= 0xC;
}
// 1단계
for (int i = 0; i < strlen(env); i++)
{
xorVal += env[i];
}
xorVal /= 30; // result = 0xC
while (index != 22)
{
if (index & 1)
v3 = inputKey[index] - 4;
else
v3 = inputKey[index] + 4;
v7[index] = v3;
v7[index] ^= xorVal;
++index;
}
printf("%s", inputKey);
// 85=5=5;=:=4?:>5=4=;=:=
}
상기 주석 1단계를 통해 xorVal을 알아낸 다음 그 xorVal과 realKey를 XOR 취하는 작업으로 거슬러 올라가야함.
#include <stdio.h>
#include <string.h>
// round 2
int main()
{
char inputKey[23] = "85=5=5;=:=4?:>5=4=;=:=";
char v7[32] = "\0";
int index = 0;
int v3 = 0;
for (int i = 0; i < strlen(inputKey); i++)
{
//v3 = inputKey[i]; // 1byte
if (i % 2 == 0)
v3 = -4;
else
v3 = 4;
inputKey[i] = inputKey[i] + v3;
}
printf("HackCTF{%s}\n", inputKey);
}
The END.
'0x02 Reverse Engineer > 0x03. Etc' 카테고리의 다른 글
Rootme Prob . ELF x86 - KeygenMe (0) | 2020.02.06 |
---|---|
KaKaoTalk MacOS Analysis (0) | 2020.01.26 |
[Rootme] Go lang Basic (0) | 2019.01.31 |
rootme elf nanometis (0) | 2018.05.22 |
rootme elf-antidebug (0) | 2018.05.22 |