안 쓰던 블로그
dreamhack rev-basic-4 풀이 본문
먼저 메인 함수를 본다.
main을 보면 구조는 이전 문제들이랑 다르지 않다
함수에 들어가 본다
RCX(입력값)을 RSP+8 주소에 가져온다
RSP에 18만큼의 공간을 준비한다
RSP주소에는 0을 넣는다
JMP한다
CMP RAX, 1C를 하는데 RAC와 1C를 비교하는 것
결과값이 ~65주소보다 크거나 같으면(JAE) EAX에 1을 넣고 RSP에 18을 더하면서 종료된다
계속 비교하며 반복하는 모습이 보이니 즉 이 부분은 for문이다 for(int i=0; i<0x1C;i++)
1C가 되기 전까지는 반복문을 돈다
안에는 CMP EAX, ECX가 있고 JE로 분기하는데, 같으면 돌아가고 다르면 EAX를 비우고(XOR EAX, EAX) 바로 리턴하러 점프한다
EAX와 ECX를 비교하는 if문이고, 조건은 != 인 셈이다
if문이 있다는 것까지 알았으니까 한 줄씩 확인해 본다
만약 입력으로 hello를 입력했다고 치면 hello는 [rsp+20] 위치에 있다
rcx, qword ptr ss: 이 부분에서 rcx로 hello를 가져온다
그 다음줄인 MOVZX EAX, BYTE PTR DS[RCX+RAX]에서 rcx+rax*1: "hello"니까 RAX에 'H'인 48이 들어간다
SAR EAX, 4를 하는데, SAR은 오른쪽 쉬프트 연산을 하는데 원래 부호를 그대로 유지한다 >>4 연산인 것이다
이 연산이 끝나면 RAX가 4가 된다
RDX에 다시 Hello를 가져온다(RSP+20 주소)
ECX에 rdx+rcx*1: "Hello"를 한다 ECX에 'H'인 48이 들어간다
SHL은 왼쪽 쉬프트 연산. ECX가 원래 48이었는데 480이 된다 << 4 연산이다
ECX를 0xF0과 AND연산. ECX가 80이 된다
지금 나온 EAX와 아까 구한 ECX를 OR연산한다
RAX는 84 (입력값 Hello 기준으로)
RDX+RCX 주소의 값을 ECX에 가져온다 RCX는 현재 24 (Hello기준으로)
RDX에 문자열을 가져온다 덤프로 따라가서 문자열 확인
0x24~0xE3까지의 문자열을 아까 <<4와 &연산 과 >>4 연산한 값을 or연산 한 값과 비교한다
연산을 다 알아냈으니까 코드로 for문 돌리면서 문자를 찾아낸다
#include <iostream>
using namespace std;
int main() {
int a[] =
{
0x24,0x27,0x13,0xC6,0xC6,0x13,0x16,0xE6,0x47,0xF5,0x26,0x96,0x47,0xF5,0x46,0x27,0x13,0x26,0x26,0xC6,0x56,0xF5,0xC3,0xC3,0xF5,0xE3,0xE3
};
for (char i = 0; i < 28; i++) {
for (char j = 0; j < 127; j++) {
int tmp = ((j<<4)& 0xF0) | (j >> 4);
if (a[i] == tmp) cout << j;
}
}
}
코드를 실행시키면 플래그를 얻을 수 있다.
플래그는 Br1ll1ant_bit_dr1bble_<<_>>
'CTF > Reversing' 카테고리의 다른 글
dreamhack rev-basic-5 풀이 (0) | 2020.09.22 |
---|---|
제출 못 한 것들 저장용 (0) | 2020.09.22 |
x64의 기초 (0) | 2020.09.22 |
wow64 file system redirection (0) | 2020.09.18 |
어셈블리 C코드 변환하기 (0) | 2020.09.17 |