상세 컨텐츠

본문 제목

2013 juniorCTF Level9 write-up

0x10 정보보안/0x13 Write-Up

by sweetchip 2013. 7. 29. 07:57

본문

반응형


서버상에 바이너리 파일 한개와 crack.txt, admin_hash 파일이 존재하는 것을 볼수 있습니다.


문제 설명을 보면


대회 rule에 말씀드린 바대로 현재 잘 풀리지 않고 있는

문제에 대한 힌트를 제공해 드리겠습니다.


=========================================================

level6 : snprintf(), truncate vulnerability

level7 : timing issue, 1초는 매우 길다!

level8 : anti reversing (elf header)

level9 : simple reversing and dictionary crack

level10 : 푸는 방법이 3가지)

1) system() 함수를 이용 (초딩)

2) 오버플로우 이용 (중딩)

3) type conversion memory leak (고딩)

=========================================================



마지막까지 최선을 다하시어 "all clear" 획득하시길 바랍니다!^^




/////////




/home/gostop/chal - 문제 바이너리입니다.


/home/gostop/admin_hash - chal 프로그램에 의해 생성된 특정 인물의

hash 값입니다. 특정 인물이 사용했던 원래의 암호가 이 문제의 키 값입니다.


/home/gostop/crack.txt - crack에 활용하는 사전 파일입니다.

이 사전을 이용할 경우 답이 나옵니다.


% 주의사항 %


대회 인증 서버에 정답 값을 brute force 하는 행위는 금지입니다.

적발될 시 그에 상응하는 조치가 있을 예정입니다.



대충 안내를 보고 문제의 의도를 파악할 수 있습니다 [브루트 포싱]


그렇다면 프로그램이 대충 어떻게 돌아가는지 분석해 보도록 하겠습니다.


int __cdecl sub_8048544(int a1, int a2)

{

int result; // eax@8

int v3; // ecx@8

unsigned int i; // [sp 28h] [bp-330h]@5

FILE *v5; // [sp 2Ch] [bp-32Ch]@5

unsigned __int8 v6; // [sp 37h] [bp-321h]@5

int v7; // [sp 38h] [bp-320h]@1

int v8; // [sp 238h] [bp-120h]@1

int v9; // [sp 338h] [bp-20h]@6

int v10; // [sp 33Ch] [bp-1Ch]@6

int v11; // [sp 340h] [bp-18h]@6

int v12; // [sp 344h] [bp-14h]@6

int v13; // [sp 348h] [bp-10h]@6

int v14; // [sp 34Ch] [bp-Ch]@1


v14 = *MK_FP(__GS__, 20);

memset(&v8, 0, 0x100u);

memset(&v7, 0, 0x200u);

if ( a1 != 2 )

exit(0);

if ( strlen(*(const char **)(a2 4)) > 0x1E )

exit(0);

v5 = fopen("/etc/dic.txt", "r");

v6 = **(_BYTE **)(a2 4);

for ( i = 0; i < v6; i )

{

v9 = 0;

v10 = 0;

v11 = 0;

v12 = 0;

v13 = 0;

fgets((char *)&v9, 18, v5);

}

*((_BYTE *)&v9 strlen((const char *)&v9) - 1) = 0;

sprintf((char *)&v8, "%s%s", &v9, *(_DWORD *)(a2 4) 1);

sprintf((char *)&v7, "/bin/echo -n %s|/usr/bin/md5sum > passwd.hash", &v8);

system((const char *)&v7);

result = puts("passwd.hash is generated.");

if ( *MK_FP(__GS__, 20) != v14 )

__stack_chk_fail(v3, *MK_FP(__GS__, 20) ^ v14);

return result;

}


소스를 보시고 정적분석과 디버거를 함께 하는 동적분석을 같이 진행하시면 chal 바이너리 인자에 asdfgh 같은


글자를 넣는다면 맨 앞 글자가 사라지고 sdfgh 가 들어가는 것을 확인하실 수 있는데,


그렇게되서 'dic내용중하나 sdfgh' 같이 문자열이 완성됩니다.


/bin/echo -n 은 줄바꿈 없이 출력이고, md5sum 은 기본제공 프로그램[?]으로 md5 해쉬를 해주는 프로그램이며


그 결과를 passwd.hash에 저장합니다.


그러므로 'dic내용중하나 sdfgh' 이런 내용을 전부다 해쉬시켜서 admin_hash의 값과 비교한 다음 평문을 구합니다.


그리고 평문에서 인자로 넘겻던 값을 구하면 그 값이 플래그가 될 것입니다.



그리고 대회당시 저는 이 부분 부터 풀지 못했는데 특정인물의 hash 값이라고 해서


/etc/passwd 에 있는 유저를 인자로 넘겨 해쉬를 만드는 것으로 추정하고 풀었는데 결국 풀지 못했습니다.


대회 후에 다시 풀어보니 dic 파일 안에 있는 것이 특정인물이었던 것을 알게 되었습니다.....


허탈하지만 문제는 풀어야 하므로 원래 작성했던 스크립트에 두줄을 추가시켯습니다.


import md5


f = open("crack.txt","rb")

a = f.read()

f.close


b = a.split('\x0a')


print len(b)

k = 0

hash = "a18003d80ddc806496c6ca03f06537d7"

for i in range(len(b)):

for j in range(len(b)):

k = 1

if md5.md5(b[i] b[j][1:]).hexdigest() == hash:

print "[!] Found!!!!!"

print "[*] plain-text : " b[i] b[j][1:]

print "[*] Flag : " b[j]

print "[*] calc num : " str(k)

raw_input("go?")




Flag : whetstone



반응형

관련글 더보기