드림핵 난이도 1단계 문제인 What-is-my-ip 를 풀어보려 한다.

 

사실 예전에 잠깐 풀어봤다가 정말 오랜만에 문제를 시도한건 안비밀

아무튼 VM서버를 접속하면 아래와 같이 자신의 IP주소가 뜨는데 

 

문제에 압축파일을 풀어보면 

 

 

위와 같이 나오고  requirements.txt에서 flask가 뜬다. 뜬금없이 말을 한 거 같지만 의외로 중요한 부분이였다.

문제를 풀기 위해 버프스위트를 사용하였고 

 

 

요청값에서 기본으로 세팅을 복사하여 붙여넣으면 위와 같이 나온다.

위 문제가 http의 헤더를 이용하는 것이였고 대중적으로 널리 알려진 취약점이 있나 찾던 중 

X-Forwarded-For: <client>, <proxy1>, <proxy2>

 

위와 같은 문법으로 쓰인다.

 

 

X-Forwarded-For: ;cat /flag

라 작성하면 

정답이 나온다.

국내에서 리버싱을 배울 수 있는 곳은 정말 한정적이다.

그나마 http://reversing.kr/ , https://dreamhack.io이며,  이외에는 영문으로 검색해야  찾아볼 수 있다.

 

Reversing.Kr

This site tests your ability to Cracking & Reverse Code Engineering. Now Challenge a problem for each environment. (Windows, Linux, .Net, Flash, Java, Python, Mobile..) Admin E-Mail: gogil@reversing.kr

reversing.kr

 

해커들의 놀이터, Dreamhack

해킹과 보안에 대한 공부를 하고 싶은 학생, 안전한 코드를 작성하고 싶은 개발자, 보안 지식과 실력을 업그레이드 시키고 싶은 보안 전문가까지 함께 공부하고 연습하며 지식을 나누고 실력 향

dreamhack.io

리버싱. kr에서는 기초적인 공부를 하고 난 뒤 직접 풀어봐야 알 수 있고 아무것도 모르고 시직 할 때는 드림핵에서 공부하는 걸 추천한다.  

 

 

아무튼 오늘 풀어볼 문제는 드림핵에 rev_basic #1 첫 번째 문제다.

 

 

문제를 다운로드하고 ida로 가지고 오면 아래와 같은 상태일 것이다.

어떠한 값을 입력하면 "Correct" , 아니라면 "Wrong"을 출력한다. 

 

IDA의 디버거를 이용해서 입력을 할 수 있지만 윈도우의 명령 프롬포트(CMD)chall.exe 파일을 드래그해서 가지고 오면 이 방식으로도 디버깅이 가능하다.

아직 문제의 답을 모르기 때문에 아무리 입력해도 "Wrong"으로 출력이 될 것이기에 한번 파해쳐 볼 것이다.

 

 

함수창main으로 쓰여있는 함수를 클릭하면 나오는 코드이자, 기본 코드 이기도 하다. 

; int __cdecl main(int argc, const char **argv, const char **envp)
main proc near

var_118= byte ptr -118h
var_18= qword ptr -18h

; __unwind { // __GSHandlerCheck
push    rdi
sub     rsp, 130h
mov     rax, cs:__security_cookie
xor     rax, rsp
mov     [rsp+138h+var_18], rax
lea     rax, [rsp+138h+var_118]
mov     rdi, rax
xor     eax, eax
mov     ecx, 100h
rep stosb
lea     rcx, aInput     ; "Input : "
call    sub_1400013E0
lea     rdx, [rsp+138h+var_118]
lea     rcx, a256s      ; "%256s"
call    sub_140001440
lea     rcx, [rsp+138h+var_118]
call    sub_140001000
test    eax, eax
jz      short loc_1400013B6

하지만 여기서 알아야 할 정보는 F5를 눌러야 더 자세히 나온다. 

그 정보 값은 어셈블리어 위에 있는 " ; __unwind { // __GSHandlerCheck " 코드다. 

 

 

눌러봤다면 화면창은 이럴 것이다.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4[256]; // [rsp+20h] [rbp-118h] BYREF

  memset(v4, 0, sizeof(v4));
  sub_1400013E0("Input : ", argv, envp);
  sub_140001440("%256s", v4);
  if ( (unsigned int)sub_140001000(v4) )
    puts("Correct");
  else
    puts("Wrong");
  return 0;
}

 

코드가  아까보다 단순해졌고 한눈에 보기 쉬워졌다. 

자세히 보면 if문 sub_140001000이 같이 있다. 이 함수는 전에 올렸던 글에도 봤었던 중요 함수라 말한 적이 있다.

 

그렇다면 해당 함수로 더 자세히 들어가 보도록 하자

_BOOL8 __fastcall sub_140001000(_BYTE *a1)
{
  if ( *a1 != 67 )
    return 0i64;
  if ( a1[1] != 111 )
    return 0i64;
  if ( a1[2] != 109 )
    return 0i64;
  if ( a1[3] != 112 )
    return 0i64;
  if ( a1[4] != 97 )
    return 0i64;
  if ( a1[5] != 114 )
    return 0i64;
  if ( a1[6] != 51 )
    return 0i64;
  if ( a1[7] != 95 )
    return 0i64;
  if ( a1[8] != 116 )
    return 0i64;
  if ( a1[9] != 104 )
    return 0i64;
  if ( a1[10] != 101 )
    return 0i64;
  if ( a1[11] != 95 )
    return 0i64;
  if ( a1[12] != 99 )
    return 0i64;
  if ( a1[13] != 104 )
    return 0i64;
  if ( a1[14] != 52 )
    return 0i64;
  if ( a1[15] != 114 )
    return 0i64;
  if ( a1[16] != 97 )
    return 0i64;
  if ( a1[17] != 99 )
    return 0i64;
  if ( a1[18] != 116 )
    return 0i64;
  if ( a1[19] != 51 )
    return 0i64;
  if ( a1[20] == 114 )
    return a1[21] == 0;
  return 0i64;
}

이제 뭔가 알듯 말 듯 한 코드의 형태가 나왔다.

 

한번 클릭해 보니 해당 값은 int,정수값인데 ida에서는 값을 변환을 시킬 수 있기에 한번 char인 문자값으로 바꿔보면 어떠한 결과가 나올까?

 

단축키 혹은 우클릭으로 해당 값을 변환시킬 수 있으니 참고하길 바란다.

 

변환한 코드

_BOOL8 __fastcall sub_140001000(_BYTE *a1)
{
  if ( *a1 != 'C' )
    return 0i64;
  if ( a1[1] != 'o' )
    return 0i64;
  if ( a1[2] != 'm' )
    return 0i64;
  if ( a1[3] != 'p' )
    return 0i64;
  if ( a1[4] != 'a' )
    return 0i64;
  if ( a1[5] != 'r' )
    return 0i64;
  if ( a1[6] != '3' )
    return 0i64;
  if ( a1[7] != '_' )
    return 0i64;
  if ( a1[8] != 't' )
    return 0i64;
  if ( a1[9] != 'h' )
    return 0i64;
  if ( a1[10] != 'e' )
    return 0i64;
  if ( a1[11] != '_' )
    return 0i64;
  if ( a1[12] != 'c' )
    return 0i64;
  if ( a1[13] != 'h' )
    return 0i64;
  if ( a1[14] != '4' )
    return 0i64;
  if ( a1[15] != 'r' )
    return 0i64;
  if ( a1[16] != 'a' )
    return 0i64;
  if ( a1[17] != 'c' )
    return 0i64;
  if ( a1[18] != 't' )
    return 0i64;
  if ( a1[19] != '3' )
    return 0i64;
  if ( a1[20] == 'r' )
    return a1[21] == 0;
  return 0i64;

해당 문자값을 모아보자면 "Compar3_the_ch4ract3r" 이고 이 값을 input에 넣어보면

 

Correct정답을 맞출 수 있다. 

+ Recent posts