[reversing.kr] Twist1 풀이
- 리버싱/reversing.kr
- 2020. 3. 13. 21:18
Twist1은 여러 안티디버깅 기법을 확인할 수 있는 문제인데 안티디버깅 플러그인도 안먹히고 코드가 중간중간 풀리는게 많아서 bp도 여러곳에 걸어주어야 하고 게다가 왜인지는 모르겠지만, OEP를 찾은 후 덤프를 떠주고 진행했는데 중간에 빠진 코드가 있어서 이것 때문에 삽질 시간이 더 길어졌다. 겨우 전부 우회를 한 후에도 키젠 부분에 페이크가 많아서 풀다보면 굉장히 지치는 문제이다. 확실히 푼사람 수가 확 줄어든 것을 보니 인내심을 충분히 갖고 풀어야 하는 문제인 것 같다.
reversing.kr Twist1 풀이
이번 문제는 Windows x32 환경에서 풀어야 하는 문제로 Twist1.exe를 실행시키면 Input 값을 받고 있다.
일단, 패킹이 된 것인지? IDA로 디컴파일이 잘 안된다. pushad나 popad를 찾아서 OEP도 찾아봤는데 근처에 jmp문을 찾을 수가 없다. (바로 ret되는데 거기도 OEP와는 거리가멀었다)
Twist라는 이름답게, PE 구조를 꼬아놓은 것인가 싶어서 각 헤더의 사이즈나 위치관련 정보도 확인해보았는데 이상한 점은 발견해지 못했다. 그래서 이제 x32Dbg로 실행시켜 보는데, 계속 Access Violation이 발생한다.
어떤 함수에서 Access Violation이 발생하게 됐는지 보려고 반환 정보를 활용해 bp를 걸어주는데 안걸린다.
EP부터 트레이싱 하다보면, 407063~40706D 반복문에 의해 아래쪽에 40715F0까지 코드가 쓰이게 된다. 코드를 그냥 두지 않고 반복문에 의해 풀리게끔 한 것을 보면 여기에 뭔가 중요한 것이 있는 것 같다.
새로 쓰인 코드에서 fs:[30]은 PEB Table의 주소이고 0x28 ^ 0x30 = 0x18로 PEB Table 구조체의 +0x18에는 Process Heap 정보가 존재하는데 0xC에 flag 값이 있기 때문에 안티디버깅의 한 방법으로 사용되기도 한다. 안티디버깅 때문에 계속 Access Violation이 났던 것 같다.
40709F 함수 안으로 들어가보면 결국 (*TEB[0x18])+0x18+0xc 값이 0x2(정상실행중)인지 확인하고 있다.
그리고 한번더 Process Heap 정보를 이용해 디버깅 여부를 검사하게 되는데 +0xC는 0x2일 경우 정상 실행인 flag이지만 0x10은 force flag로 0x0일 경우 정상 실행으로 인지한다.
위 2개 우회로 끝난 줄 알았는데 하나가 더있다. PEB 구조체의 +0xC에는 Ldr 구조체가 있고 +0x10 부터 주소영역을 검사하게 된다. 이 부분을 한번 더 우회한 후 진행하다보면, 아래와 같이 mov로 4071BD에 0xE9, 0xA3을 쓰면서 jmp문이 생기게 되고 해당 주소로 점프하면, 그곳이 OEP이다.
조금만 트레이싱하다보면 문제 해결이 될줄 알았는데 생각보다 복잡하고, 코드를 푸는 과정이 있기 때문에 중간에 코드 패치도 안되기 때문에 한번 재시작하면 우회 과정을 계속 반복해야 하기 때문에 OEP에서 덤프를 떠주었고 이제 IDA로 디컴파일이 되기 때문에 문자열 "Wrong"이 쓰이는 함수를 봐보면, Wrong/Correct 분기가 되는 부분을 확인할 수 있다.
분기문 위쪽 함수를 조금더 분석해주면 끝날 줄 알았는데, 계속 Exception 코드로 빠지는 것을 보면 안티디버깅 코드가 더 있는 것 같다. 안티디버깅 플러그인 적용도 해보고, 콜스택에서 반환값 찾아서 bp도 걸어보고 임포트하는 안티디버깅 함수에도 bp를 걸어보고 해봤는데 계속 뭐가 바뀌었다가 됐다가 bp가 걸렸다가 안걸렸다가 (중간에 풀리는 코드도 있고 등등의 이유로) 하여튼 잘 안돼서 한줄한줄 트레이싱하기로 했다. 이문제의 핵심은 진짜 인내심인 것 같다.................
인내심을 갖고 트레이싱하다보면, zwQueryInformationProcess를 총 3번 우회해야 한다. 전달되는 2번째 인자 값 별로 우회하는 방법이 다르기 때문에 구글링해보면서 풀면 좋을 것 같다.
그렇게 모든 우회를 마치게 되면, 드디어 input 값 검사로 들어간다.
워낙 길기 때문에 여기서부터는 상세한 풀이 과정은 설명하지 않겠다. 문제의 이름처럼 상당히 꼬아놨는데 의도된 것인지 아닌지는 모르겠지만 페이크도 몇개 있고 한 함수내에서 비교적 간단하게 인풋을 검사할 수도 있는데 중간중간 jmp나 call, nop이 상당히 많고 중간에 써주는 코드도 많아서 bp도 잘 걸어야 한다. 또한 정답 문자열이 한번에 나오고 strcmp 해주는 구조가 아니라 한 바이트씩 검사해주는 구조라 한줄한줄 트레이싱 하면서 확인해주어야 한다.
대충 정리하면 아래와 같은 방식이다. 어떻게 연산해서 몇번째 글자를 어떤 값으로 확인하는지를 보면서 한글짜씩 구하면 정답값을 구할 수 있다. 참고로 나는 첫번째 입력값 제외 나머지는 구했는데 첫번째는 역연산이 잘 안돼서 파일 Input 창에서 브루트포싱해주었다.
[40B000] = input[0] ror 0x6 = 0x5
[40B001] = (input[0] ror 0x6) rol 0x4 = 0x50
[40B002] = ((input[0] ror 0x6) rol 0x4) ^ 0x34 = 0x64
[40B000] == 0x49 ?
[4076D0] == 0x64
al=0x41 input[0]
dl-0x42 input[1]
cl=0x43 input[2]
dh=0x44 input[3]
bh=0x45 input[4]
bl=0x46 input[5]
[40b970] ^ 0x12 = 0x53
[40cce0] = input[2]
[40cce4] = input[5]
[40cce8] = input[0]
[40ccec] = input[1]
[40774f] = 1
....
'리버싱 > reversing.kr' 카테고리의 다른 글
[reversing.kr] WindowsKernel 풀이 (0) | 2020.03.15 |
---|---|
[reversing.kr] Easy ELF 풀이 (0) | 2020.03.15 |
[reversing.kr] ransomware 풀이 (0) | 2020.03.12 |
[reversing.kr] Direct3D FPS 풀이 (0) | 2020.03.11 |
[reversing.kr] Position 풀이 (0) | 2020.03.10 |