콘치의 리얼리티 3000% 리버싱 튜토리얼 (3)-1

By conchi | September 3, 2016

콘치의 리얼리티 3000% 리버싱 튜토리얼 (3)-1



안녕하세여.

3편으로 찾아온 콘치에여.

뭔가 오늘은 기분이 좋지 않아서…

드디어 여러분들이 손꼽아 기다리던 재밌는거 하는데…

드립이 좀 노잼일거 같아요…

양해좀 바랄게요..ㅎㅎ…

네? 그전부터 핵 노잼 드립 잔치였다구여?

녜…

대전으로 오셈 ㅎㅎ




여러분^^!!! 오늘은 우리함께 리버싱을 해 볼거에요!!(소름 돋는 우디르급 태세전환)

그동안 계속해서 노잼지식들을 습득했으니 이제 이것들을 이용해서 리버싱을 해보자구용.

실행파일만 가지고 우리가 처음 만들었던 소스코드로 돌아가는 충격적인 작업이랄까….

으앙 넘나 설레는것!! 헤헿!!


# 요녀석을 소스코드로ㅎ


준비물 - 무료 디버거 툴, 맨 정신, 열 손가락, 예전에 만들어둔 프로그램(.exe)

작업 환경 - windows 7 32bit


우선 리버싱을 하기 위한 무료 디버거툴을 구하러 갑시다.

여러분들에게 어떤 좋은 툴을 소개시켜 줄까… 고민하다가 Ollydbg라는 디버거툴을 이용하기로 했어요.

별 기능 없어 보이지만 생각보다 알찬 녀석입니다.

일단 가장 큰 장점은 무료이고 사용방법도 간단하지만 필요에 따라

여러 플러그인들을 사용해서 많은 기능을 이용할 수 있기 때문에 골라봤습니다. 헤헤ㅋㅋㅋㅋ


설치는 공식 홈페이지에서 다운받아 하도록 해요.


ollydbg.de 홈페이지 들어가시면 왼쪽편 Files 이라는 목록에 여러 버전의 ollydbg가 준비되어 있어요.

우리는 오늘 ollydbg 1.1 버전을 받을거에요.

각각 설치해보시면 아시겠지만 조금씩 기능이 다릅니다. 헤헿!!


+) 우리는 32bit PE 바이너리를 분석하기 때문에 ollydbg 1.1 버전을 사용하기로 했습니다. (사실 32bit PE 바이너리의 경우, ollydbg 어떤 버전을 써도 상관은 없음)

분석을 당하는 녀석(디버기)이 몇 bit 바이너리인지는 상당히 중요합니다. 왜냐면 이에 따라서 디버거의 종류 혹은 사용 가능한 디버거의 버전이 달라지기 때문이죠. 우리가 사용하고자 하는 ollydbg 1.1버전으로는 32bit PE 바이너리는 분석 가능하지만, 64bit PE 바이너리를 분석할 수 없습니다.


아마 다운받고 나면 .zip파일로 압축되어 있는 odbg110 파일을 볼 수 있을거에요.

적절한 위치에 압축을 풀어주시고 관리자 권한으로 실행해주세요 ~~



ollydbg를 쓸 준비가 되었습니다. ㅎㅎ!!!!!

더블클릭 해서 실행하시면 아마 무슨 경고창같은게 두 개 혹은 한개 뜰거에요.

흠.. 그럴땐 그냥 일단 확인 버튼 누른다음에 종료한 후,

오른쪽 버튼 눌러서 관리자 권한으로 실행하시면 문제가 해결됩니당.

헤헤 몰랐졍?ㅎㅎ?


# ★극★뽁★


다시 실행시켜보세요



;;; 위협적인 창이 나오네여 –;;

그런데 뭐… 말그대로 UDD 디렉토리가 ollydbg폴더 안에 없어서 그런거니까

하나 만들어서 경로 잡아주면 다시는 안뜰꺼에요. 일단은 확인 눌러서 그냥 넘어갑시당.

[파일] - [open]을 해서 우리가 만든 파일을 open해봅시다!! +_+!!

우리가 만들었던 실행파일은 뭐 여러분이 따로 경로를 지정해주지 않았으면

[내문서] - [Visual Studio 2015] - [Projects] - [여러분이 만든 프로젝트 이름] - [Debug] 안에서 얌전히 누군가의 손길을 기다고 있을꺼에요.

혹시나 지난시간 만들어둔 프로그램이 없다 싶으면 다시 만드시면 됩니당 :) 소스코드는 이렇게 생겨먹었어요.


#include <stdio.h>

int main()
{
printf("hellow!!");
return 0;
}


새로 만드시는 분은 위의 소스를 참고해주세요.

그냥 이것저것 누르지 마시고 그대로 컴파일 하시면 됩니다.

Debug, x86이에요. (지금은 릴리즈 모드 아님)

두근두근잼


# ?? 누구세염 ??


왠지.. 어디서 망하는 냄새가.. ㅎㅎ..?

엔트리포인트(EP)를 잘 못찾고 있는듯한 우리의 올리디버거에요.

여기에서 엔트리 포인트는 프로그램이 시작되는 부분을 말해요.

그런데 이런 시작부분을 못찾는다고하니.. 고난이 예상되네요 ㅠㅠ…

하지만… 지..진정해요 여러분 ㅎㅎ.. (동공지진) ㅇ..일단 침착하게 확인을 눌러봅시다.



그러면 비어있는 도스 창 하나랑 정체불명의 코드를 뿜어내고 있는 ollydbg가 보일거에요.

음…뭐지? 뭐지 이건?…

뭔가.. 예전에… 리버싱 책에서 본거랑은..다른 모양새인데? 뭐지? ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ????

ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ??????? 누구세영?ㅎㅎ?


# 전 이만ㅎㅎ(총총)


…하고 싶지만 일을 해야 먹고사는 scv같은 존재라서..

멘탈잡고 알려드리기로 마음먹었어요ㅎㅎ

뭔가… 이런걸 원한게 아닌데..

부들부들 떨리는 손으로 x를 누르고 그냥 게임이나 한판 하고 싶겠지만

진정하시고 화면을 보세요.

우린 해낼 수 있을거에여 ㅎㅎ..

아마도 ㅎㅎ..


# 콘치가 생각한 화면


# 현실


ㅎ… 인생은 실전이라는 말이 낭낭하게 떠오르네요 ㅎㅎ….주륵 정말 무슨말인지 하나도 모르겠네요 정말 ㅜㅜ..


자 그럼 지금부터 멘탈 잡고 침착하게 왜 이런 일이 우리에게 일어났는지부터 알아봅시다.

아 혹시 우리가 만들었던 것과 다른 프로그램 아니냐구요??(음모론)



아니에요ㅠㅠ IDA님에게 똑같은 파일을 줬더니 이렇게 콘치가 상상하던 모습이 나왔어요 ㅠㅠ..

올리디버거…바보… 크흡….너란남자 지겨워 이제 헤어져ㅠ_ㅠ..


는 헤어질 수 없는 운명이에요 우린 ㅎ0ㅎ!

도대체 우리의 printf는 어디로 사라지고 이런 정신없는 못생긴 문자들만 화면에 가득 차 있는지 알아봐요 !! ^0^!!!!


우선 들어가기에 앞서 올리디버거의 사용법을 알려줄게요.

콘치랑 이번 시리즈에서 사용하게 될 단축키는 음… 음..

없졍!

은 훼이크 ㅜㅜ.. ㅋㅋㅋ 올리디버거 사용할 때 많이 쓰이는 단축키들로 몇 개 알려드릴게요!


[F7] - 함수 안으로 진입할 때 사용되어져요. 함수를 좀더 자세하게 분석하고자 할 때, 함수안으로 직접 진입하여 분석할 수 있게해줘여.

[F8] - 얘는 함수를 만나도 진입하지 않고 그냥 통째로 실행시키고 넘어가버려요. 꼭 분석하지 않아도 되서 그냥 넘어가야 할 때 주로 사용합니다.


[F7]과 [F8]을 좀 더 쉽게 설명해드리자면 제가 영진이라는 잘생기고 귀여운 친구네 집을 가고 있어요.

그런데 아니 이 친구가 본인이 살고 있는 동네만 알려주고, 집이 어딨는지는 알려주지 않았어요;; 극혐;;..

그래서 영진이를 만나야 하는 콘치는 한집한집 들어가서 영진이 집이에요?

영진이 있나 볼게용 하고 둘러보게 되요.

이게 [F7]이에요.

한참을 들어가서 확인하고 다시 나오고 하던 콘치는 빡쳐서 이제 집안으로 들어가지 않고

그냥 집 앞에서 영진찡 나와랑! 하고 소리를 지르게 되었어요.

집안에 있는 사람들은 당연히 영진이네 집이 아니니까 그냥 별 반응이 없었어요.

이게 [F8]이에요.

집에 들려서 하나하나 자세하게 확인할 때 사용하는 것과, 그냥 집단위로 넘어가는 것.

함수로 직접 진입해 하나하나 확인가능 한 것과, 함수단위로 그냥 실행시켜 넘어가는 것.

이게 F7과 F8의 차이입니다.

아! 뒷이야기는 유료서비스입니다 고객님 ^^

돈 들고 찾아오셈 ㅎㅋ..


[F9] - run의 의미를 가지고 있어요. 누르는 순간 프로그램이 끝까지 실행이 됩니다. 푸와아아앙ㄱ 못 멈춤 마치 아무도 나를 막을 수 없으셈… 이런거…?

[F2] - 브레이크포인트(Break Point)를 설정합니다. 요게 걸려있으면 걸려있는 위치까지 실행되고 한번 멈추게 되요. 사용방법은 걸고 싶은 주소로 키보드 위아래 키를 눌러가면서 이동한 후, 그냥 필살기 쓰듯이 비장하게 눌러주면 됩니다. ㅎㅎ! 간단 그자체 (비장하게 안 해도 걸리긴함..ㅎㅎㅋ)

[Ctrl] + [F2] - 프로그램을 재시작할 때 사용되는 단축키에요. 분석하다가 헐.. 여기로 오면 안되는데… 망ㅋ… 할 때 눌러서 다시 처음으로 돌아가요. 잘 안쓸거 같지만 엄청난 길이의 반복문을 탈출할 때, 브레이크 포인트를 거는 타이밍을 잘못 맞추면 ㅎㅎ 아 뚜렣헤루훟뛟뛟 하면서 눌러야해요 ㅎㅎ… 뭐 앞으로 하다보면 알게될꺼에요 ㅎㅎ…

[Ctrl] + [G] - 원하는 주소로 가야할 때 사용되는 단축키에요. Ctrl + G를 누르면 쪼마난 창이 하나 뜨는데 거기다가 내가 이동하고 싶은 주소를 적으면 거기로 한번에 이동시켜줘요. 텔레포트 같은거랄까..


말로 설명하니까 잘 모르겠죠? 그럼 눌러보면 됩니다. ㅎㅎ! 고장 안 나니까 눌러보세요. ㅎ0ㅎ!




우리는 main이라는 함수안에 printf라는 함수를 이용해서 hellow라는 문자가 출력되는 프로그램을 만들었어요.

그런데 이 화면을 자세히 보고 있자니.. main은커녕 printf라는 함수는 오간데 없네요.

과연 이 프로그램이 우리가 만든 게 맞긴 할까요 ㅠㅠ…


[F9]를 꾹 눌러보세요.


그러면 또 우리가 만들었던 프로그램이라는 걸 증명하듯이

아래쪽에 내려가있는 까만 도스창에 hellow라는 문자가 출력 될 거에요.

그럼 이 코드들 어딘가에 우리가 만들었던 소스가 들어 있다는 건데… 도대체 어디 있는 걸까요? ㅠㅠ?

우리가 만든 소스는 어떤 형태의 어셈블리어로 존재하고 있는 걸까요?


아참 지금 눈에 보이는게 바로 지난시간에 이야기했던 어셈블리어입니다.


기계어가 되기 전의 단계라던 그거에요.

그나마 사람이 볼 수 있는 단계랬는데 전 처음에 보고 이게 기계어 인줄 알았어요ㅠㅠ…

자 그럼 지금부터 진짜!!

레알 본격적으로 프로그램을 분석해볼까요? ㅋㅋ..




어셈블리 코드를 한번 봅시다.



프로그램을 열면 아마 이렇게 멈춰 있을거에요.


맨앞에 까만색 배경에 흰색 숫자 있는 부분을 ‘주소’라고 부릅니다. 16진수로 쓰여져 있어요~!

그 옆에 칸에 있는 E9 050F0000라는 말은 저도 무슨말인지 모르겠어요(?)

이 부분에는 OPCODE가 들어갑니다. 실제 명령어를 의미하는 부분이나, 지금당장 우리가 볼 것은 그 옆에 있는 어셈블리 명령이니 PASS!

궁금하신 분들은 구글 검색창에 OPCODE 혹은 OP코드라고 검색해보시면 원하는 정보를 얻으실 수 있을거에요.


그 옆에 있는 부분이 바로 우리가 이제 해석해야하는 어셈블리 명령어입니다.


JMP ConsoleA.mainCRTStartup 이라고 적혀있네요.

jmp 명령어가 사용되었습니다. 뚜둔!


jmp명령은 특정한 위치로 가서 명령을 실행하라는 의미를 가지고 있습니다.

보통은 [JMP] [함수주소] 가 오는 경우가 많지만 우리 눈에는 주소가 아니라 뭔 이상한 함수이름같이 보이네요.

저 부분을 더블클릭 해보면 사실 jmp [함수주소]로 되어있지만,

올리디버거의 기본 옵션 때문에 저렇게 문자로 보이는 듯합니다.

진짜임ㅎㅎ!


그럼 위의 JMP명령은 ConsoleA.mainCRTStartup으로 날아가라는 의미가 되겠군요?

하나씩 F7을 눌러가면서 확인해봅시다.


한참을 뛟뛟 거리면서 신명나게 F7을 갈기다보면 ㄷㄷ..;;

다음과 같은 경고창이 우릴 반겨줍니다.



?뀨?

왜 나오라는 printf는 안나오고 이런게 나오지?? 나 뭐 잘못한 거 없는데여 ㅎㅎ…? 저한테 왜이러심….. 주륵….



심지어 hellow! 문자열이 출력되는 함수는 실행되지도 않았는지 아무것도 안나오네요.

이 말은 우리가 printf가 있는 곳이 아니라 엉뚱한곳으로 왔다는말…


아니 시작할 때 젤 처음으로 알려준 곳에서부터 시작했는데 이게 무슨 일이야!!

빼애애애애앵ㅇ!!!!


그러게요… 다.. 제 불찰이네요

침착하게 확인을 누르고 더 진행해보려 하지만 똑같은 경고창만 떠버리네요

쩍.. ㅠㅠ..뭔가 잘못되고 있는거 같아여 ㅜㅜ 침착하게 다시 생각해보도록 해요.



침착하게 앉아서 커피나 한잔 하면서 방귀같은 여러분들의 삶을 30초정도 되돌아보면 다음과 같은 결론을 내릴 수 있어요.


  1. 올리디버거가 시작점을 못 찾아서 우리는 이상한데서 시작했다.

  2. 하지만 우리가 찾는 printf를 실행시키는 부분은 이소스 어딘가에 있다. (그러니까 무작정 f9를 누르면 실행이 되겠지)


1번은 방금 확인한 듯해요 ㅠㅠ.. 그러고 보니..

시작할 때 엔트리포인트(시작점) 못찾았다고 경고창 떴었는데… 뭐한거지? ㅎㅎ.. 여러분들을 상대로 농락함.. 농락잼


흠흠 그러면 2번에 희망을 가지고 다시 한 번 찾아봅시다.


사실 이 글을 안봐도 될 정도의 실력을 가진 분들이라면

하 저인간은 뭐 이런걸로 고민을 하징ㅋ 하고 생각할지도 모르겠네요ㅎㅎ! 답답보스!!


콘치가 생각해낸 방법은 두가지정도가 됩니다.


첫 번째 방법은 아까 앞쪽에서 보여줬던 IDA를 이용한 방법이에요.

IDA에서 이 프로그램을 열면 우리처럼 이런 고민을 안 해도 됩니다. 혼자서 알아서 main()을 찾아주거든요.

그러니까 비싼거져ㅋㅋ 헤헤 ‘3’ 몸값 오져…


두 번째 방법은 IDA를 구하기 힘든 저같은 서민을 위한 방법입니다 ㅠㅠ..


[Ctrl] + [F2]를 눌러서 다시 프로그램을 시작시키고 우리를 혼돈으로 이끌었던 곳에서 키보드로 쭉쭉쭉쭉 내려가다 보면



이렇게 생긴 부분이 있습니다. 주소는 여러분들도, 저도 모두 다르니 신경쓰지 마세요!


JMP exe파일이름.main이라는 부분이 보일꺼에요 +_+!!


그럼 그 위를 마우스로 한번만 클릭 한 후,

한줄 전체가 회색이 되거든 [F2]를 눌러서 브레이크포인트를 걸어줍니다. 호롤롤롤 이제 다와 갑니당 +_+


나는 여기서부터 진행하고 싶어염!

하지만 앞에 부분은 어떻게 되든 상관없으니 여기까지 알아서 실행되게 해주세염! 하려고 브레이크 포인트를 걸었어요.

이 부분에 브레이크 포인트를 걸고 F9를 누르시면 여기까지 알아서 잘 와집니다.

우리가 처음부터 F7을 눌러서 실행시켰던 거랑은 다르게 잘 될꺼에요.

브레이크 포인트가 걸려있기 때문에 F9를 누르면 이 부분에서 한번 멈추게 됩니다.


자 그러면 이제 저기서 어떤 일이 벌어지는지 확인하기 위해, 저 명령을 실행(F9)시켜볼게요 :3



딱 멈춰있는 모습입니다.

주소는 당연히 다르니까 신경 ㄴㄴ해.

JMP 명령과 main이라는 부분만 주목해주세요!

지금은 회색으로 되어있는 저 앞까지 실행된 상태에요.

그러니까 우리가 저 부분을 실행시키고 싶으면 저 줄을 지나가야지 저부분의 명령이 실행되는 거에요.ㅎㅎ


그럼 저기로 가면 어떤 일이 벌어지는지 한번 가봅시다.

[F7]을 눌러서 저곳에서는 어떤 일이 벌어지는지 한번 들어가 보아요!



짜잔! 이렇게 생긴 곳이 우리를 기다리고 있습니다.


저기 아래쪽에 PUSH OFFSET ConsoleA.??_C@08NPMMOAP@hellow 뭐시기저시기 되있는부분 보이시나용?

헤헤 우리가 원하는 hellow 출력 부분이 맞나 아닌가 한번 확인이나 해보자구용 ㅇ_ㅇ..


조금 천천히 f8을 눌러줍니다.

아참 이때 아래쪽에 내려 가있는 검은 도스창을 함께 볼 수 있게 해주세요.

그러니까 올리디버거 화면을 조금 작게 해두고 검은 창의 상태가 보이도록요 ㅎㅎ!


그렇게 f8을 한줄한줄 눌러주시다 보면 CALL명령을 지나자마자 검은창에 hellow가 생기는 걸 볼 수 있을거에요.



이렇게 헤헤 :3

우리는 제대로 찾아왔음을 ㅠㅠ 확인 한거에요 ㅠㅠㅠㅠ넘나 감격 ㅠㅠㅠㅠ넘나


#include <stdio.h>

int main()
{
printf("hellow!!");
return 0;
}


우리 눈에는 이렇게 보이던 소스코드가 컴퓨터 안에서 저렇게 변한거에요.

음… 상상이나 했나요? ㄷㄷㅎ..ㅋ




우리는 앞으로 이렇게 널부러져 있는 어셈블리어를

★직★접★ 저렇게 원래의 코드로 바꾸는 연습을 할거에요.

왜? 이게 리버싱이니까요 ^0^?!


exe로 되어있는 실행파일을, 어셈블리어로 변경시켜 이걸 보고 원래 코드는 이랬을것이고,

이런 코드에서는 이런 취약점이 나온다! 하고 찾거나 해당 코드의 동작을 알아내는거죠.

어때요 재밌겠죠?


우리 이번에 올리디버거로 분석하면서 c언어로 되어있는 부분 한군데라도 봤나요? 못봤죠?


앞으로도 계속 이런 환경에서 분석 해야해요. ㅠㅠ

아 물론 존엄하신 헥스레이님은 자동으로 exe파일만 슉 던져도 c언어로 바꾸어 주겠지만… 헥스레이 없으면요?

님들 리버싱 안하실꺼?

님들의 눈이, 님들의 손이 직접 헥스레이가 되고싶지 않으시나요?

(ㅎㅎ 유혹중 ㅎㅎ)


음.. 어셈블리어도.. 뭐도 아~~~~~~~~무것도 모르는데

헥스레이에 보이는 C코드 만으로는 정확한 분석을 하기가 어려워요.


헥스레이로 보여 지는 코드는 결국 정적인 코드이기 때문에 우리가 직접 실행해 볼 수가 없어요.

이건 중요한거에요.

방금 우리는 main함수까지 찾아왔고, 그 안에 있는 어셈블리 명령들을 실행해서(이때 F7, F8을 눌렀었죠!)

우리가 분석한 프로그램이 실제로 hellow가 출력되는 프로그램이었다는 걸 확인했어요.

그리고 헥스레이는 본인의 규칙에 맞게 소스코드로 해석을 하기 때문에 때로는 헥스레이가 분석해놓은 C언어 보다

어셈블리어를 보는게 더 이해가 잘되는 경우도… 종종 있고… 직접 동적으로 분석을 해야 할 일이 발생하기도 합니다. ㅇㅋ?

그래서 우리는 어셈을 보고 헥스레이가 C소스로 만들어 주듯이, 핸드레이를 해볼 필요가 있다 이거에욤. ㅇㅋ?


후 힘들댱


뭔가 억지스러운 부분이 0.1%정도 있는 거 같지만 결론은 할 줄 알아서 나쁠 건 전혀 없으니

열심히 공부해보도록 합시당 호호 ^0^!

그럼 저 흉측한 어셈블리어를 영롱한 c소스로 바꾸는 행위는 다음시간에 하도록 해요 :)


안농!!


난 퇴근!



….은뻥 ^^!

가기 전에 마음에 걸리는 게 있어서 알려드리고 갈까 해요.

보통은 저렇게 엔트리 포인트(EP)를 못 찾고 그러지 않아요 ㅋㅋ

왜냐면 Ollydbg 옵션에 프로그램 시작 할 때, 엔트리 포인트부터 시작하게 설정하는 부분이 있거든요ㅎㅎ

Options – Debugging options – Events – Entry point main module 라디오 버튼을 체크하시고 ok누르시면 됩니다 ㅎㅎ…!

이렇게 쉽게 하는 방법이 있는데 왜 우린 먼길을 돌아왔는가 궁금하실거에요.


엔트리 포인트를 찾는다는건 정말 중요해요.

그 프로그램의 시작이 어딘지를 알 수 있는 부분이기도 하고 분석의 시작이기도 한 부분이니까요.

그래서 많은 패커들이나 안티 리버싱 기법들에서는 이러한 엔트리 포인트 지점을 바꿔버리거나 숨겨둡니다.

그러면 당연히 분석이 어려워 지겠지요.

커스텀 패커의 경우는 언패커(패킹을 푸는 도구)가 존재하지 않는 경우도 존재하기 때문에

본인이 EP를 찾아 떠나야 하는 경우가 종종 발생하기도 합니다.

그럴때를 대비해서 EP가 제대로 잡히지도 않는 경우가 있다는것을 콘치는 여러분께 알려드리고 싶었습니다. :)


그러니 너무 노여워 하지 마시고 다음시간에 핸드레이나 해봅시댱 퍄퍄

그럼 전 이만 ~~!


comments powered by Disqus