
C++ 리버싱 문제
C++ 리버싱은 처음 해본거 같은데 생각보다 어려워서 놀랐다.
C 랑 큰 차이 없지 않을까 생각하고 시작했다가 큰코다쳤다..
문제의 목표는 올바른 password를 찾는것이다.

문제파일로 주어지는 것은 ch25.bin 파일이다.

먼저 프로그램을 실행시켜 보았다.
터미널에서 ./ch25.bin 이라고 입력하면 실행이 되는데
그냥 실행시켰더니 usage : ./ch25.bin password 라면서 사용법이 출력된다.
./ch25.bin hello 라고 password를 인자로 넣어서 실행시켜 주니
비밀번호가 틀렸다는 안내 문구가 출력된다.

IDA 라는 디스어셈블러를 이용해서 ch25.bin 파일을 열어보았다.
c로 만들어진 프로그램이라면 오른쪽에 깔끔하게 어셈블리어가 잘 보이는데
c++로 만들어서 그런지 알아볼 수 없는 복잡한 내용들이 보였다.

그렇다고 아예 알아볼 수 없는 것은 아니다.
주목한 부분인 이 부분인데
_ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_EPKS3_ 를 call 한다음에
그 결과값에 따라서 password incorrect 를 출력하거나, Bravo 를 출력하고 있는 모습이 보인다.
저 부분을 자세히 보기로 했다.

_ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_EPKS3_ 를 더블클릭하면 이런 화면으로 넘어간다.
아래쪽에 compare 가 있는걸로 보아서 비밀번호를 검증하는 루틴인 듯 하다.
시작 주소인 08048CF7 을 잘 기억해 둔다.

여기부터는 Kali 리눅스에서 gdb 라는 디버깅 도구를 이용해 분석했다.
gdb는 기본적으로 설치되어 있고,
gdb ./ch25.bin 을 입력하면 해당 파일을 디버깅 할 수 있다.

info func 라고 입력하면 ch25.bin 내에 있는 함수들의 목록을 보여준다.
아까 기억해뒀던 08048CF7 을 찾아보면
bool std::operator==<char, std::char_traits<char>, std::allocator<char> (std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*) 라고 적혀있는데
이것이 아까 IDA 에서 봤던 _ZSteqIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_EPKS3_ 이랑 똑같은 것이다.

b bool std::operator==<char, std::char_traits<char>, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*)
라고 입력해서 해당 함수에 breakpoint를 걸어준다.

r(run) 을 입력하면 프로그램을 실행시킬 수 있다.
주의할 것은 password를 인자로 넣어줘야한다는 것이다.
그래서 r hello 같은 방식으로 입력을 해줘야 한다.
프로그램을 실행시키면 아까 브레이크포인트를 걸어둔 곳에서 프로그램이 멈추게 된다.

다시한번 IDA 에서 08048CF7 의 어셈블리를 살펴본다.
eax 에 ebp + arg_4 (0x0c) 를 저장하고, 다시 그값을 esp +4 가 가리키는 주소로 옮기고 있다.
그다음 다시 eax 에 ebp + arg_0 (0x08) 을 저장하고, 그 값을 esp 가 가리키는 주소로 옮긴다.
그리고 나서 compare 를 수행하는데
위에서 가리키고 있는 두 주소중 어느곳에 비밀번호가 숨어있는듯 하다.
일단 compare를 하는 부분의 주소가 08048D0A 이니 거기까지 gdb에서 프로그램을 진행시킨다.

breakpoint 로 부터 ni 를 입력하면 프로그램을 한 칸씩 진행시킬 수 있다.
ni 를 네 번 입력해면 08048D0A 에서 멈추는것을 볼 수 있다.

여기서 info reg 명령어를 이용하면 레지스터의 상태를 확인할 수 있다.
아까 사용되었던 eax, esp 레지스터 값만 살펴본다.
eax 에는 0xffffd104, esp 에는 0xffffd0d0 가 들어있다.

스택의 내용을 보려면 x/20wx <주소> 이런식으로 입력하면 된다.
esp 에 저장되어있던 0xffffd0d0 주소의 스택을 살펴봤더니
eax에 저장되어있던 0xffffd104 가 들어있는것이 보인다.

이번엔 eax 저장된 주소인 0xffffd104 의 스택을 살펴본다.
여기에는 0x0805ccc 라는 값이 저장되어 있는데,
이것도 뭔가 주소처럼 보인다.

마지막으로 0x08050ccc 주소로 찾아가보면
뭔가 데이터가 저장되어 있는것처럼 보인다.
여기를 읽을 때 주의해야 하는데 리틀 엔디안 방식으로 저장이 되어있기 때문이다.
예를들어 맨 처음있는 0x65726548 의 경우 이걸 그대로 읽는 것이 아니라
48 65 72 65 처럼 두개씩 잘라서 맨 뒤부터 읽어야 한다는 것이다.

메모장에서 리틀 엔디안으로 적혀있는 16진수 값들을 순서대로 써 주었다.

CyberChef(https://gchq.github.io/CyberChef)에서 hex 값을 디코딩해주면 숨겨진 password를 찾을 수 있다.

ch25.bin 프로그램을 실행시키면서 찾은 비밀번호를 넣어보면
Bravo 라고 뜨는것을 볼 수 있다.
'워게임 > Root Me' 카테고리의 다른 글
[Root Me] Directory traversal - 웹해킹 (31) | 2022.07.09 |
---|---|
[Root Me] JSON Web Token - Introduction - 웹해킹 / JWT (70) | 2022.07.06 |
[Root Me] Flash - Authentication - 웹해킹 / FFDEC (56) | 2022.06.28 |
[Root Me] Insecure Code Management - 웹해킹/ Directory Listing / git (42) | 2022.06.25 |
[Root Me] PE x86 - 0 protection - 리버싱 / Ollydbg (56) | 2022.06.22 |