ssoL2 TISTORY

[reversing.kr] 2. Easy Keygen / 간단 설명 본문

challenge/reversing

[reversing.kr] 2. Easy Keygen / 간단 설명

ssoL2 2020. 1. 3. 19:56

하2루

 

1일 1리버싱 인정? 어 인정~

 

 

이번엔 readme가 있구만 한번 읽어 봅시다.

 

 

으음........

5B134977135E7D13인 뭔가를 찾으면 될 거 같은 느낌쓰..

 

 

Easy Keygen을 실행시켜보자

 

inputName을 적으라 해서 KIMSOJEONG을 적음

이후 시리얼 번호를 저 위에 걸로 해봄

 

wrong 출력

 

 

 

흠 그렇다면

저 위에 5B134977135E7D13인

시리얼 번호에 맞는 NAME을 적고

이 시리얼을 넣으면

 

키값이 나올것이라 예상하고 

올리디버거 ㄱㄱ

 

 

 

 

스트링 검사 해봤더니만

correct라는 매우 수상한 스트링 발견.

 

바로 가보자

 

 

오케이. 

함수 시작부분을 찾아서 해보자잉

 

 

첫 문제 Easy Crack에서 했던 것 처럼

메인으로 추정되는

첫 부분에 breakpoint 걸고 시작.

 

 

실행해봅니당.

 

 

input Name 

OK

 

 

 

입력 받고

 

 

이건 입력한 INPUT NAME에 대한 길이.

ECX = 길이.

자세한건 밑에 참조.

 

 

 

 

 

 

       rep    : ecx > 0인 동안 명령어 반복

   repz, repe    : Zero Flag가 1이고, ecx > 0인 동안 명령어 반복 

repnz, repne   : Zero Flag가 0이고, ecx > 0인 동안 명령어 반복

 

 

 

 

 

mov edi, example.00407034 "Hello World !"      ;  ASCII

repne scas byte ptr es:[edi]

not ecx

 

- 출발지로 "Hello World !" 라는 문자열이 00407034 번지에 들어가 있는데 이 문자열을 edi에 넣는 코드가 보인다.

- repne 나왔다. rep 계열의 명령어는 문자열 컨트롤에 자주 쓰이는 어셈블리 명령어 중 하나라고 한다.

  rep는 repeat의 약자라고 생각하면 쉽다. rep 계열 명령어는 주로 ecx 레지스터와 함께 자주 사용되는 편이며,

  ecx > 0인 동안 어떠한 행위를 처리한다.  

- repne를 사용한 것으로 보아 Zero Flag가 0이고, ecx가 0보다 클 경우 scas 명령어로 eax와 edi 값을 반복해서 비교한다. 현재 edi에는 "Hello World !" 가 들어 있는 상태인데, 이런 행위를 하는 이유가 무엇일까?

- 위 연산에 대한 ecx 결과 값은 FFFFFFF1 이라고 한다. FFFFFFFF - FFFFFFF1 을 하게 되면 0xE (10진수 14)가 되는데 바로 이 값은 "Hello World !"의 글자 수다.

- not ecx로, FFFFFFF1을 0xE로 변환하는 역할을 한다.

- 결국 위와 같은 형태의 코드 패턴이 등장한다면,

  특정 번지수에 있는 문자열의 길이를 구하는 것이라고 생각해도 크게 틀리지 않을 것이다.

 

mov edi, X

repne scas byte ptr es:[edi]

not ecx

 

 

 

 

ECX랑 EDX랑 XOR하는데,

ECX는 input name 첫번째 스트링이고

EDX는 0X10임.

 

 

INPUT NAME PUSH할때

0x10 0x20 0x30도 넣었었다.

 

이때 넣은 0x10임.

 

 

암튼 둘이 XOR해서

ECX에 저장.

 

 

그리고 PUSH

 

 

 

반복 돌기전 다시 초기화.

입력했던 INPUTNAME인 12345 주소를 EDI에 저장.

 

첫번째 줄에 EBP +1해서 1로 저장해놓고.

 중간 줄에 ECX는 다시 입력 NAME 길이로 저장해놓고

둘이 비교.

 

 

어셈블리 언어에서의 DEC a 는

C 언어에서의 --a; 와 같다고 볼 수 있다.

 

 

이렇게 반복문 5번 도는거지.

길이 만큼..

 

첫부분에 이거는

 

0x10 0x20 0x30 을 차례대로

xor하기 위해 ESI라는 변수 레지스터를 사용함.

 

 

 

암튼 계속 반복문 돌면서

이렇게

XOR한 값들이 순서대로 쌓임(?)

1 XOR 0x10 = 21

2 XOR 0x20 = 12

3 XOR 0x30 = 03

...

이런식으로 !!

211203..등등 이렇게 순서대로 쌓임

아스키 기준임 이건 !!!!!!

주소에 이 값이 저장되는게 X

 

 

 

 

JLE : Jump less or equal

<=

 

 

 

ESP+74에 있는 값을 담는게 아니라

EAX에 ESP+74의 주소 자체를 담는것

 

 

INC : operand 값 +1

 

 

 

 

 

 

 

 

그리고 최종적으로 된 이 값을

 

 

첫번째 문자부터 하나씩 비교해서 틀리면 WRONG출력되게 함.

 

 

 

 

따라서

5B134977135E7D13은

XOR 10 20 30을 반대로 해서 나온 값인데..

 

10은 00001010

20은 00010100

30은 00011110

 

4B 33 79 67 33 6E 6D 33

 

아스키 코드 변환표에 의해

K3yg3nm3

 

 

 

https://dojang.io/mod/page/view.php?id=740

 

C 언어 코딩 도장: 85.6 ASCII 코드표

ASCII 코드는 영문 알파벳 대소문자 52개, 숫자 10개, 특수 문자 32개, 널 문자 1개로 이루어져 있으며 나머지는 제어 문자입니다. 0x00(0), NUL: 널 문자 0x0A(10), LF: 개행(Line Feed), 줄바꿈 0x0D(13), CR: 복귀(Carriage Return) 0x00~0x1F, 0x7F(0~31, 127): 제어문자 또는 비인쇄 문자 0x20(32): 스페이스(공백) 0x21~0x2F(33~47), 0x3A~0x40(5

dojang.io

 

https://johnst.tistory.com/206

 

리버싱 흔히 사용하는 패턴

정리 내용은 리버스 엔지니어링 바이블 책의 내용 입니다. 문자열 컨트롤은 프로그래밍의 기본 중의 기본이라고 한다. 별도의 문자열 처리 라이브러리를 이용해 문자열을 컨트롤하는 경우도 많겠지만 기본적인 str..

johnst.tistory.com

 

Comments