Hacking/[Reversing]IOLI CrackMe

IOLI CrackMe 0x03

양선규 2023. 4. 8. 02:45
728x90
반응형

IOLI CrackMe 0x03 입니다.

리버싱은 한번도 해본 적 없었습니다만..

Leviathan 1번 문제가 리버싱 문제였기에, 리버싱을 공부하기 위해 풀어본 문제입니다.

 

문제 파일 링크입니다.

https://github.com/mattetti/IOLI-crackme

 

GitHub - mattetti/IOLI-crackme: crackme exercises with instructions to learn in a safe environment

crackme exercises with instructions to learn in a safe environment - GitHub - mattetti/IOLI-crackme: crackme exercises with instructions to learn in a safe environment

github.com

 

저는 Kali에서 Radare2를 사용해 문제를 해결하였습니다.

 

 

문제 파일

 

문제 파일들입니다. 오늘은 crackme0x03 문제를 풀어보겠습니다.

 

 

문제파일 실행

 

./crackme0x03

 

문제파일을 실행하면, Password를 입력하라고 합니다.

 

 

인증 실패

 

1234를 입력해 보았습니다. Invalid Password! 라고 하면서 쫓겨났네요.

그렇습니다. 이 문제는 Password의 값이 무엇인지 리버싱을 통해 알아내는 문제입니다.

 

 

radare2로 문제파일 실행

 

r2 -d crackme0x03

r2 : radare2를 실행하는 명령어

-d : 디버깅 모드로 실행

 

먼저 r2명령어를 이용해 문제파일을 실행시켜줍시다.

0xf7fb3450 값은 현재 위치입니다.

 

 

프로그램 분석

 

aaaa

aaaa : 프로그램을 분석하는 명령어

 

a를 입력해도 되고 aa를 입력해도 되지만, aaaa가 가장 상세히 분석됩니다.

 

 

함수 리스트 출력

 

afl

afl : 분석된 함수를 리스트 형태로 출력하는 명령어

 

"main" 함수가 보이시나요? main함수를 기준으로 분석해보도록 하겠습니다.

 

 

현재위치 변경

 

s @ main

s : 현재 위치 변경 명령어

 

s 명령어를 사용하여 현재 위치를 main함수의 시작위치로 변경하였습니다. 명령어의 인자를 쓸 땐, @를 적은 후에 써야 합니다.

 

 

main 함수

 

pdf

pdf : 현재위치 기준으로 disassemble된 함수들만 출력합니다. @를 추가해 인자를 지정하여, s 명령어로 현재위치를 변경하지 않고도 사용할 수 있습니다.

 

위쪽 부분은 main함수가 생성되는 부분이고.. ( push ebp / mov ebp, esp )

 

 

아래쪽 부분

 

84b4, 84bb 부분을 보면 IOLI_Crackme_Level_0x03 문자열을 출력하고

84c0, 84c7 부분을 보면 Password: 문자열을 출력한 후

84da 부분을 보면 scanf 함수로 뭔가 입력받고 있습니다.

 

그 전에 84d3 부분에 0x8048634 값이 이용되고 있는데, 해당 값이 뭔지 한번 보도록 합시다.

 

 

%d

 

ps @ 0x8048634

ps : 입력값 또는 입력주소에 대한 데이터를 string(문자열)형태로 출력하는 명령어

 

해당 값은 %d 였네요. 바로 밑에 scanf 함수가 있었으니, 10진수 형태로 입력을 받는다는 의미 같습니다.

 

 

뭔가 막 계산한다

 

scanf 함수 이후에 뭔가 막 계산을 하다가, "sym.test" 함수로 이동하게 됩니다. ( call sym.test 부분 )

sym.test 함수를 확인해보도록 합시다.

 

 

sym.test 함수

 

pdf @ sym.test

 

pdf명령어로 sym.test 함수를 확인하였습니다.

847a 부분을 보시면 je 0x804848a 명령어가 있는데요, 이건 앞서 cmp 비교구문의 결과가 동일한 값일 경우, 지정된 위치로 점프하는 명령어입니다. ( 왼쪽 화살표를 따라가면 됨 )

cmp 명령어는 입력된 두 값을 비교하는 명령어입니다. 두 값이 같을 경우 ZF(Zero Flag) 값이 1이 되고, je 명령어는 ZF 값이 1일 경우 점프를 실행하는 것입니다. 

 

그러니까, 8477 부분에서 eax와 arg_ch의 값이 같을 경우 점프하는 겁니다. ( dword는 자료형임 )

eax와 arg_ch가 대체 뭐길래 비교를 하고, 점프를 통해 각기 다른 결과로 이어지는 걸까요?

 

어떤 값이 존재하는지, 확인해 봐야 할 것 같습니다.

 

 

break 설정

 

db 0x08048477

db : break point를 설정하는 명령어

break point : 프로그램을 실행할 경우, 지정된 break point에서 더 실행하지 않고 멈추게 됨

 

db 명령어로 break point를 지정하였습니다. 설정된 위치는, 앞서 cmp 명령이 있던 부분입니다.

cmp 명령을 통해 비교를 진행한 후 je 명령으로 점프하니, cmp 명령에서 대체 뭘 비교하는지 알기 위해서 설정한 것입니다.

 

 

프로그램 실행

 

dc

dc : 프로그램을 실행하는 명령어, 실행중인 상태로 분석할 수 있음

 

dc명령어로 프로그램을 실행했고, password값으로 "1234" 를 입력하였습니다.

이후 break point에서 멈췄다는 안내문이 출력되었습니다.

 

 

break가 걸려있다

 

pdf 명령어로 확인해보면, cmp 위치에서 멈춰있는 걸 알 수 있습니다. ( "b" 문자열 )

지금은 프로그램이 실행되던 도중 멈춘 것이고, 따라서 eax와 arg_ch 값을 확인할 수 있습니다.

 

 

0x4d2

 

dr eax

dr : 레지스터값을 확인할 수 있는 명령어, 인자없이 사용하면 모든 레지스터가 출력된다

 

eax엔 0x4d2라는 값이 저장되어 있습니다. 10진수로 바꿔볼까요?

 

 

내가 입력한 값

 

? 0x4d2

 

? 명령어 뒤에 숫자나 문자열 등을 붙이면, 다양한 형태로 변환해 출력해줍니다.

eax 값은, 10진수로 "1234" 였군요.

제가 아까 dc 명령어로 프로그램 실행할 때, password로 1234를 입력했었죠?

제가 입력한 password가, eax에 들어가 있는 겁니다.

 

이제 감이 좀 잡히는 것 같은데요..

 

 

ebp+0xc

 

자, 우리가 찾아야 할 값은 arg_ch 인데요

친절하게도 3행 부분을 보시면 arg_ch @ ebp+0xc 라는 부분이 있습니다.

이것은 arg_ch의 값이 ebp+0xc 위치의 값과 동일하다는 걸 의미합니다.

ebp+0xc 위치의 값을 확인해 보도록 합시다.

 

 

hexdump

 

px 0x30 @ ebp+0xc

px : 입력값을 hexdump(16진수)형태로 출력해주는 명령어

0x30 : 해당 위치부터 30바이트 만큼 보여달라

 

ebp+0xc 위치부터 30바이트만큼의 값을 16진수 형태로 불러왔습니다.

다만 해당 위치부터 지정된 만큼 불러오는 것이기 때문에, 저게 전부 ebp+0xc 의 값이 아닙니다. 다른 값도 섞여있습니다.

맨 처음 "242b 05" 이부분만 ebp+0xc 의 값입니다.

 

하지만 저걸 바로 읽으면 안됩니다. little endian 방식으로 저장되어 있기 때문입니다.

little endian 방식은, 쉽게 말해서 반대로 읽는 겁니다. 242b05 -> 052b24 이렇게 2개씩 반대로 읽어야 합니다.

big endian 방식이란 것도 있는데, 이건 정방향으로 읽는 방식입니다.

 

 

338724

 

? 0x052b24

 

해당 값은 10진수로 "338724" 였습니다.

결과적으로 cmp 명령어는 우리가 입력한 값인 "1234" 와 "338724" 를 비교하는 것이었습니다.

 

그렇다면 "338724"가 password 인 걸까요?

 

 

338724 입력 후 다시 분석

 

doo

dc

doo : 프로그램을 다시 실행하고 싶을 때 사용하는 명령어

 

doo 명령어를 입력 후, 다시 dc명령어로 프로그램을 재실행합니다. 이번에는 password로 예상되는 338724를 입력하였습니다.

 

 

visual mode

 

V

p

p

V : Visual mode 실행

p : Visual mode에서 출력화면을 변경할 수 있음

 

V 명령어로 Visual mode를 실행한 후, p를 두번 눌러 해당 화면으로 이동했습니다.

 

je를 통해 점프

 

S : 스텝오버, shift+s 단축키로 사용 가능

스텝오버 : 하나의 OP code 실행( 명령어 한줄 실행 ), call 명령을 만나면 해당 함수 안으로 직접 들어가진 않음

스텝인투 : 하나의 OP code 실행, call 명령을 만나면 함수 안으로 진입함.

 

shift+s 를 두번 눌러 프로그램을 약간 진행시켰습니다. 예상한 대로 je 명령문을 통과해 지정된 위치로 점프하였습니다.

따라서 cmp 비교구문 통과에 성공했다는 것입니다.

 

이제 증명할 일만 남았습니다. 프로그램을 직접 실행하고 338724를 입력해 보겠습니다.

 

 

clear

 

password는 예상대로 "338724"였습니다!!

 

main 함수에서 cmp 명령 비교구문을 찾아낸 후, 해당 값에 우리가 입력한 값이 들어있다는 것을 알게 되면서,

비교되는 수인 338724가 password 라는 것을 알 수 있었습니다.

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

https://www.youtube.com/watch?v=2vMSfvtQuVo

참고한 영상입니다.

728x90
반응형

'Hacking > [Reversing]IOLI CrackMe' 카테고리의 다른 글

IOLI CrackMe 0x02  (0) 2023.04.09
IOLI CrackMe 0x01  (0) 2023.04.09
IOLI CrackMe 0x00  (0) 2023.04.09