KISA 1번 리버싱 문제

2017. 5. 31. 14:120x02 Reverse Engineer/0x03. Etc

728x90

으흐흐.. 약 5시간 만에 푼 바이너리이다. 

역시 리버싱은 술 한잔  걸치고 풀어야 제맛인 것 같다. 

지금부터 Writeup 작성을 할 것이다.


바이너리를 무작정 실행해보면 신기한 화면이 툭하고 튀어나온다.

               [그림 1. 바이너리 실행] 


로딩 바가 진행되다 보면, 다음과 같은 화면이 나온다. 노래도 나온다. 근데 밤에 들으면 좀 무서운 노래인 것 같다. (처음엔 그랬따...)


              [그림 2. 바이너리 실행] 


척 보면 척 !! KeyGen이 필요한 문제라고 생각된다. 

게씽을 해보면 시리얼 값은 숫자 10개로만 이루어져 있어야 한다. 


우측 하단에 ip checking 하는것이 있는데 분석결과 이건 아무 필요없는 기능이었다.


잘못된 시리얼 값을 입력해보자. 5숫자 초과 해보았다. 다음과 같은 에러 메시지박스를 띄워준다.

[그림 3. 바이너리 실행]

[그림 4. 바이너리 실행]






이제 올바르게 숫자를 10개 지정해서 테스트 해보았다.

로딩바가 원 상태로 돌아가는 현상이 일어난다. 

권한이 없어 REVOKE 되는 이벤트를 부여한 것 같다.

[그림 5. 바이너리 실행]

[그림 6. 바이너리 실행]


어떤 방식으로 프로그램이 실행되는 지 파악했으니 제대로 분석하기 위해 OllyDbg를 이용하자.


메인함수 주소를 살펴보았다. 메인함수 주소를 알아야 프로그램에 접근이 가능하기 때문이다. (이건 뭐 다들 알죠,..?)


[그림 7. 프로그램 메인함수 찾음]


시리얼 값 입력받는 곳에 왔다.

입력 한 시리얼 값 : 11111 - 22222 


내가 입력한 시리얼은 스택에 쌓이게 된다. 스택에는 먼저 들어온 데이터가 

"주소가 높다"


지금 해당 바이너리에서 [local.113]과 [local.112]에 시리얼 값이 들어감을 알 수 있다.

[그림 8. 시리얼 입력하는 부분에 bp 걸었음] 


스택을 한번 살펴보자.


11111(DEC) -> 2B67(HEX) addr 0019EA88

22222(DEC) -> 56CE(HEX) addr 0019EA8C


                           [그림 9. 스택]


그 후 cmp [local.143], 0x0 이라는 명령어가 나온다. 이 값은 GetDigItemInt의 반환값을 의미한다. 

int를 받아오게 되면 반환값은 1이 되어야 한다.

            [그림 10. GetDIgItemInt의 원형] 


만약에 시리얼값이 숫자가 아니면 해당 함수로 분기한다. 


[그림 11. 잘못된 분기 - 잘못된 시리얼]


그 다음 유심히 보아야 하는 루틴은 ' 과연 ! 이 시리얼의 범위는 어디 까지 인가 ' 


[그림 12. 시리얼의 범위를 찾음] 


함정일수도 있는데... (여기서 한 10분정도 헤맸던 기억이 난다) 엔디언을 변환시키는 구문이 있다. 

ntohl 함수를 이용하기 때문이다.


나에게 5시간을 할애하게 만든 죽이고 싶은 루틴의 시작지점이다. 

welcome to hell party ! 

[그림 13. 중요한 루틴 ...! ]


5번 돌면 EDX에 값을 툭... 떨궈준다. 이걸 눈치채는데 엄청난 시간이 걸렸다.


첫번째로 2B67이 나온다. 2B67은 첫번째 시리얼 값이다.


[그림 14. 첫번째 시리얼 값 추출] 


또 다시 적절하게 걸어둔 BP를 이용하여 5번 실행 


0EB786E2가 나온다. 

[그림 15. 저 숫자가 무엇이냐... ]


고민 고민끝에 알게 된 공식 1개 

2B67 * 56CE = 0EB786E2 (WOW)

첫번째 시리얼 * 두번째 시리얼


BP를 사용하여 쭉쭉 진행하다보면 0EB786E2 -> 0EB75B7B가 나온다. 


[그림 16. 2번째 공식 추출]


공식 2번째 

0EB786E2 - 2B67 = 0EB75B7B

(첫번째 시리얼 * 두번째 시리얼) - 첫번째 시리얼


[그림 17. 3번째 공식 추출]


공식 3번째 

0EB786E2 - 0EB75B7B = 56CE

- 0EB75B7B  = 56CE - 0EB786E2 

56CE = 0EB786E2  - 0EB75B7B  

(첫번째 시리얼 * 두번째 시리얼) - 첫번째 시리얼 + 두번째 시리얼

0EB75B7B + 56CE = 0EB7B249 (이런 공식이 암산이 안되서 엄청나게 헤맸다...)



0EB7B249 ^ FFFFFFFF = F1484D86 (마지막 비교하는 부분) 


F1484D86이 어떻게 나왔느냐...? 

이것을 보려면 조금 더 깊숙히 루틴을 봐야한다 (즉 ,bp를 걸지말고 보아야 한다. 3번째 공식 이후로)

[그림 18. 최종 공식 추출] 


페이로드 작성 


#include <stdio.h>

int main(void)

{

int flag_1=0; 

int flag_2=0; 

int result = 0;

for(int i=10000; i<=99999; i++) 

{

for(int j = 10000; j<= 99999 ; j++)

{

flag_1 = i;

flag_2 = j;


result = 0xffffffff ^(flag_1 * flag_2)-flag_1+flag_2;


if(result == 0x5417AC0E)

{

printf("flag1 = %d , flag2 = %d\n", flag_1,flag_2);

printf("good\n");

break;

}

else

continue;

}

}

return 0;

}



결과 

여기보면 약 10개 이상의 페이로드가 추출되는데, 이 문제의 짜증나는 점은 

올바른 복호화가 되지 않으면, 결과 값이 나오지 않는다. 

노래가 있는 이유가 지루하지마라고 있는것같다 . ㅋㅋㅋㅋ 

                         [그림 19. 결과 페이로드]


정답

                                  [그림 20. 플래그]

'0x02 Reverse Engineer > 0x03. Etc' 카테고리의 다른 글

피카츄 리버싱 5부...  (0) 2017.06.05
피카츄 리버싱 4부...  (0) 2017.06.05
피카츄 리버싱 3부...  (0) 2017.06.05
피카츄 리버싱 2부...  (0) 2017.06.05
피카츄 리버싱 1부...  (4) 2017.06.04