분야 : 리버싱
이번 문제는 겁나 쉬운 문제이므로 빨리빨리 하도록 하겠습니다.
일단 이 문제는 아이다를 키면 겁나 쉬운문제
올리디버거는 약간 그냥 그런 문제가 됩니다...
(망할 헥스레이 갑...)
일단 아이다를 키고 구조를 보면...
WTF.....
그러나 짱짱리버서 오타해커군이 KSIA 세미나에서 그런말을 하였습니다.
누가누가 분석을 적게하면서 많이 볼수잇나...
음 그래 난 짱리버서이니 하겠지...는 무슨 일단
TEXT VIEW로 가서 EP를 봅니다.
.text:00401000 push ebp
.text:00401001 mov ebp, esp
.text:00401003 and esp, 0FFFFFFF8h
.text:00401006 sub esp, 8
.text:00401009 cmp ds:IsDebuggerPresent, 0
.text:00401010 jz short loc_40101B
.text:00401012 mov eax, 1
.text:00401017 mov esp, ebp
.text:00401019 pop ebp
.text:0040101A retn
어서 디버거 성님이 계시네요.
그렇지만 실행하는게 아니므로 PATH
그러나 다음 난관
.text:0040101B mov eax, ds:?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z ; std::endl(std::basic_ostream<char,std::char_traits<char>> &)
.text:00401020 push eax
.text:00401021 push ecx
.text:00401022 mov ecx, ds:?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A ; std::basic_ostream<char,std::char_traits<char>> std::cout
.text:00401028 push offset asc_402124 ; "------------------------------"
.text:0040102D push ecx
.text:0040102E call sub_401390
.text:00401033 add esp, 0Ch
.text:00401036 mov ecx, eax
.text:00401038 call ds:??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z ; std::basic_ostream<char,std::char_traits<char>>::operator<<(std::basic_ostream<char,std::char_traits<char>> & (*)(std::basic_ostream<char,std::char_traits<char>> &))
.text:0040103E mov edx, ds:?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z ; std::endl(std::basic_ostream<char,std::char_traits<char>> &)
.text:00401044 mov eax, ds:?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A ; std::basic_ostream<char,std::char_traits<char>> std::cout
.text:00401049 push edx
.text:0040104A push ecx
.text:0040104B push offset aSuperHardHouse ; "Super hard houseKey Protection"
.text:00401050 push eax
.text:00401051 call sub_401390
.text:00401056 add esp, 0Ch
.text:00401059 mov ecx, eax
.text:0040105B call ds:??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z ; std::basic_ostream<char,std::char_traits<char>>::operator<<(std::basic_ostream<char,std::char_traits<char>> & (*)(std::basic_ostream<char,std::char_traits<char>> &))
.text:00401061 mov ecx, ds:?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z ; std::endl(std::basic_ostream<char,std::char_traits<char>> &)
.text:00401067 mov edx, ds:?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A ; std::basic_ostream<char,std::char_traits<char>> std::cout
.text:0040106D push ecx
.text:0040106E push ecx
.text:0040106F push offset asc_402124 ; "------------------------------"
.text:00401074 push edx
.text:00401075 call sub_401390
.text:0040107A add esp, 0Ch
.text:0040107D mov ecx, eax
.text:0040107F call ds:??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z ; std::basic_ostream<char,std::char_traits<char>>::operator<<(std::basic_ostream<char,std::char_traits<char>> & (*)(std::basic_ostream<char,std::char_traits<char>> &))
.text:00401085 mov eax, ds:?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z ; std::endl(std::basic_ostream<char,std::char_traits<char>> &)
.text:0040108A push eax
.text:0040108B push ecx
.text:0040108C mov ecx, ds:?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A ; std::basic_ostream<char,std::char_traits<char>> std::cout
.text:00401092 push offset asc_402124 ; "------------------------------"
.text:00401097 push ecx
.text:00401098 call sub_401390
.text:0040109D add esp, 0Ch
.text:004010A0 mov ecx, eax
.text:004010A2 call ds:??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z ; std::basic_ostream<char,std::char_traits<char>>::operator<<(std::basic_ostream<char,std::char_traits<char>> & (*)(std::basic_ostream<char,std::char_traits<char>> &))
.text:004010A8 mov edx, ds:?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z ; std::endl(std::basic_ostream<char,std::char_traits<char>> &)
.text:004010AE mov eax, ds:?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A ; std::basic_ostream<char,std::char_traits<char>> std::cout
.text:004010B3 push edx
.text:004010B4 push ecx
.text:004010B5 push offset aHideFunctionIn ; "******HIDE FUNCTION INFO******"
.text:004010BA push eax
.text:004010BB call sub_401390
.text:004010C0 add esp, 0Ch
.text:004010C3 mov ecx, eax
.text:004010C5 call ds:??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z ; std::basic_ostream<char,std::char_traits<char>>::operator<<(std::basic_ostream<char,std::char_traits<char>> & (*)(std::basic_ostream<char,std::char_traits<char>> &))
.text:004010CB mov ecx, ds:?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z ; std::endl(std::basic_ostream<char,std::char_traits<char>> &)
.text:004010D1 mov edx, ds:?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A ; std::basic_ostream<char,std::char_traits<char>> std::cout
.text:004010D7 push ecx
.text:004010D8 push ecx
.text:004010D9 push offset asc_402124 ; "------------------------------"
.text:004010DE push edx
.text:004010DF call sub_401390
.text:004010E4 add esp, 0Ch
.text:004010E7 mov ecx, eax
.text:004010E9 call ds:??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z ; std::basic_ostream<char,std::char_traits<char>>::operator<<(std::basic_ostream<char,std::char_traits<char>> & (*)(std::basic_ostream<char,std::char_traits<char>> &))
.text:004010EF mov eax, ds:?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A ; std::basic_ostream<char,std::char_traits<char>> std::cout
.text:004010F4 push offset aInputFunctionN ; "Input function number to execute : "
.text:004010F9 push eax
.text:004010FA call sub_401390
.text:004010FF lea ecx, [esp+10h+var_4]
.text:00401103 push ecx
.text:00401104 push offset Format ; "%d"
.text:00401109 call ds:scanf
.text:0040110F mov edx, [esp+18h+var_4]
.text:00401113 push edx
.text:00401114 call sub_401130
.text:00401119 add esp, 14h
.text:0040111C xor eax, eax
.text:0040111E mov esp, ebp
.text:00401120 pop ebp
.text:00401121 retn
KIAA........
이게 전형적인 c++입니다.
겁나 어렵... 게 보이지만 분석 조금만 해보다 보면..
std::cout<<""<<std::endl (일반적으로 std는 using namespace std; 로..)
해석하면 print 해주고 나서 기능 부분을 입력받습니다.
어셈에 지겨울 때 쯤...
저는 hex-ray 성님을 꺼내 간단하게 줄입니다.
에프뽜이브!!!!!
int __cdecl sub_401130(int a1)
{
int result; // eax@3
char v2; // [sp+0h] [bp-24h]@4
if ( a1 == 19960215 )
{
result = printf("Givemethecake\n");
}
else
{
if ( a1 == 20131117 )
{
printf("Input password : ");
scanf("%s", &v2);
result = sub_4011C0();
}
else
{
result = puts("Wrong ");
}
}
return result;
}
만약 19960215가 나오면 givemethecake 띄웁니다
(이 글을 보는 여러분은 매년 2월 15일날 저에게 생일케잌을 주셔야 합니다 끆)
... ㅈㅅ
일단 20131117을 누르면 password를 누르라는게 뜹니다. ㅎㅎ
그리고 sub_4011C0 함수로 이동하게 되는데요...
이 함수로 이.동
int __usercall sub_4011C0<eax>(const char *a1<esi>)
{
signed int v1; // eax@4
char v2; // dl@5
char v3; // dl@5
char v4; // dl@5
const char *v6; // [sp-4h] [bp-5Ch]@2
int v7; // [sp+0h] [bp-58h]@4
int v8; // [sp+4h] [bp-54h]@4
int v9; // [sp+8h] [bp-50h]@4
int v10; // [sp+Ch] [bp-4Ch]@4
int v11; // [sp+10h] [bp-48h]@4
int v12; // [sp+14h] [bp-44h]@4
int v13; // [sp+18h] [bp-40h]@4
int v14; // [sp+1Ch] [bp-3Ch]@4
int v15; // [sp+20h] [bp-38h]@4
int v16; // [sp+24h] [bp-34h]@4
int v17; // [sp+28h] [bp-30h]@4
int v18; // [sp+2Ch] [bp-2Ch]@4
int v19; // [sp+30h] [bp-28h]@4
char Dest; // [sp+34h] [bp-24h]@6
char v21; // [sp+44h] [bp-14h]@5
char v22; // [sp+45h] [bp-13h]@5
char v23; // [sp+46h] [bp-12h]@5
char v24; // [sp+47h] [bp-11h]@5
char v25; // [sp+48h] [bp-10h]@5
char v26[11]; // [sp+49h] [bp-Fh]@5
if ( strlen(a1) >= 0x1E )
{
v6 = "Buffer overflow!";
return puts(v6);
}
if ( strcmp(a1, "Ehdvlfdl") )
{
v6 = "not match";
return puts(v6);
}
puts("Unlock success!");
v7 = 100;
v11 = 100;
v8 = 108;
v13 = 108;
v18 = 108;
v9 = 119;
v10 = 106;
v12 = 118;
v14 = 102;
v15 = 101;
v16 = 111;
v17 = 102;
v19 = 0;
v1 = 0;
do
{
v2 = *((_BYTE *)&v8 + 4 * v1);
*(&v21 + v1) += *((_BYTE *)&v7 + 4 * v1);
*(&v22 + v1) += v2;
v3 = *((_BYTE *)&v10 + 4 * v1);
*(&v23 + v1) += *((_BYTE *)&v9 + 4 * v1);
*(&v24 + v1) += v3;
v4 = *((_BYTE *)&v12 + 4 * v1);
*(&v25 + v1) += *((_BYTE *)&v11 + 4 * v1);
v26[v1] += v4;
v1 += 6;
}
while ( v1 < 12 );
return sprintf(&Dest, "%s", &v21);
}
음...음... 예
이 부분 해석하면 만약에 패스워드가 Ehdvlfdl 라면 sprintf 함수 소환
아니면 틀림
그러면 Ehdvlfdl 입력하고 난 다음 부분에 sprintf 에 찍힐 곳이 정답이므로..
v7 = 100;
v11 = 100;
v8 = 108;
v13 = 108;
v18 = 108;
v9 = 119;
v10 = 106;
v12 = 118;
v14 = 102;
v15 = 101;
v16 = 111;
v17 = 102;
v19 = 0;
v1 = 0;
do
{
v2 = *((_BYTE *)&v8 + 4 * v1);
*(&v21 + v1) += *((_BYTE *)&v7 + 4 * v1);
*(&v22 + v1) += v2;
v3 = *((_BYTE *)&v10 + 4 * v1);
*(&v23 + v1) += *((_BYTE *)&v9 + 4 * v1);
*(&v24 + v1) += v3;
v4 = *((_BYTE *)&v12 + 4 * v1);
*(&v25 + v1) += *((_BYTE *)&v11 + 4 * v1);
v26[v1] += v4;
v1 += 6;
}
while ( v1 < 12 );
return sprintf(&Dest, "%s", &v21);
이 부분에 집중합니다.
이 부분은 12 번 돌린다는 건데
저 위를 아스키 코드로 바꿔서 하는게 정답이므로 일단 저는 출제자이므로 코딩은 알아서..ㅎㅎ
ascii 로 변환하면
Key is dlwjdvlfeofl
'Write-up' 카테고리의 다른 글
[DPCTF 2013] 안드로이드 아청아청 문제 (0) | 2013.11.17 |
---|---|
서울호서전문학교 중고생정보보호올림피아드 2번문제 풀이 (0) | 2013.09.07 |
중고생정보보호올림피아드 write-up (0) | 2013.09.07 |
제 1회 주니어 해킹방어대회 (0) | 2013.07.27 |
제 2회 청소년 화이트해커 경진대회 (2) | 2013.05.26 |