CodeEngn Reversing Basic_Level07

문제에서 힌트를 준다. 하드의 이름을 이용하여 시리얼을 생성하나보다.

일단 실행해 보았다.

아무 값이나 넣고 버튼을 누르면 이러한 에러 메시지가 뜬다.

referenced string을 이용해 볼 수 있겠다. PEiD로 패킹여부를 체크해 보자.

패킹이 안 되어 있으니 그대로 올리디버거에 올려보았다.

referenced string을 찾았다. 위 두 문자열이 시리얼로 보여 입력해 보았지만 둘 다 에러메시지를 출력한다.

시리얼로 보이는 두 문자열과 성공/에러 메시지에 bp를 걸고 진행해 보았다. 확인을 위해 입력 값으로는 저 값이 아닌 더미 값을 입력하였다.

시리얼같은 문자열이 push되는 곳에서 멈추었다. 다음 코드를 읽어보니 나의 C 드라이브 이름을 push하고, lstrcatA를 호출한다. 이전 코드를 읽어보니 GetVolumeInformationA 함수를 호출한다. 여기서 내 드라이브의 이름을 받아오는 것 같다.

GetVolumeInformationA 함수 문서를 보면 정확히는 root 디렉토리의 이름을 받는 것 같다. C가 아니라 다른 드라이브에 있다면 문제와는 다르게 작동하지 않을까 한다.

lstrcatA는 인자로 넣은 두 문자열을 붙이는 함수이다.

쭉 진행을 하면 4562-ABEX와 드라이브 이름이 붙여진 문자열을 가공한다. 이후 L2C-5781 문자열에 가공된 문자열을 다시 붙인다.

최종적으로 L2C-5781(가공된문자열) 의 형태가 된다. 그리고 그 문자열을 입력값과 비교한다. 나의 드라이브 이름을 가지고 만든 시리얼은 L2C-5781EaFtive4562-ABEX이다. 이 값을 입력해 보았다.

그렇다면 문제로 되돌아가자. 요구사항은 드라이브 이름이 CodeEngn일 때 어떻게 되냐를 찾는 것이다. 그렇다면 문자열을 가공하는 알고리즘에 주목해 보자.

lstrcatA함수 뒤쪽 부터가 문자열이 가공되는 부분이다.

DL에 2를 넣고, 주소가 가리키는 값에 1을 더한다. 포인터는 DWORD이다. 처음 더한 주소보다 1 높은 주소에도 1을 더한다. 이렇게 4개의 주소에 들어있는 값을 가공한다. 그리고 DL을 1 감소시킨다. 즉, DL을 카운터로 이용하여, 4개의 주소에 있는 값에 1씩 더하는 일을 2번 반복한다는 것이다.

cmp하는 부분이 없는데, dec instruction은 계산 후 적절한 flag를 설정해주기 때문에 별개의 cmp가 필요 없다.

메모리 덤프에서 해당 주소에 있는 값을 찾아보자.

해당 위치에는 가공하고자 하는 문자열이 들어있다. 한 바퀴를 돌았을 때의 메모리 덤프이다.

주소가 DWORD이지만 리틀 엔디언으로 맨 끝에 있는, 문자열의 앞에서부터 1바이트 만큼을 조작한다. 그래서 앞의 네 글자만 가공이 된다.

즉, 이 알고리즘은 붙여진 문자열의 앞 4글자에 각각 2를 더하는 알고리즘이다.

CodeEngn의 Code부분에만 2씩 더해져, EqfgEngn이 될 것이다. 즉 CodeEngn이 어떤 것으로 변경되느냐에 대한 답은, flag는 EqfgEngn이다.


tags: writeup, reversing, pe file, windows, keygen, x86asm