드림핵 리버싱 강의를 듣고 나면 마지막 트랙에서
드림핵이 제공하는 리버싱 베이직 문제들을 풀어볼 수 있게 된다
rev_basic_0 문제 이전에 있는 patch 문제는
단순히 한 함수를 무시하게 조작해주면 끝나는 것이기 때문에
자세히 어셈블리어를 다루지 않아도 된다고 생각해 0부터 시작합니다
블로그 작성자 본인도 어셈블리어를 해석해본 경험이 적어 많이 부족하겠지만
할 수 있는 선까지의 해석해보겠습니다
1. x64bug 해석
본 함수의 코드들인데 여기에서 주목해야 할 점은 correct와 wrong을 출력해주는 부분이다
이 이전에 있는 함수에서 해당 문자열을 고를 반환값을 줬을 가능성이 높기 때문이다
call challo.7ff796861000
따라서 위의 코드 속 함수 주소를 더블 클릭 해주면 우리가 해석해야하는 함수의 코드들이 나오게 된다
이번 문제는 0번 문제답게 오른쪽에 바로 정답이 존재하지만
어셈블리어 학습을 위해 굳이 어셈블리어를 해석해보자
이 함수에서 쓰이는 어셈블리어 함수 종류
mov | 두 번째에서 첫 번째로 데이터 이동 |
sub | 캐리 포함하지 않은 뺄셈 |
lea | 오프셋(데이터 영역) 값을 레지스터로 로드 |
call | 프로시저 호출(함수 호출) |
test | and 연산 결과 값 플래그로 |
jne | 결과 값 0 아니면 분기(이동) |
jmp | 무조건 분기 |
add | 캐리 포함하지 않은 덧셈 |
ret | 스택에 push된 주소로 복귀(리턴) |
(이전 포스트의 레지스터 목록 참고)
rcx에 있던 값을 rsp+8에 이동시키고 rsp에 38을 뺀 값을 적용한다
= 이 함수를 위한 스택 위치로 변경
7FF7...에 위치한 데이터 값(Compar3_the_str1ng)을 rdx에 로드한다
rsp+40에 있는 입력한 문자를 rcx에 로드한다
그리고 JMP & strcmp를 진행해, strcmp(문자가 같으면 0을 반환함) 반환 값을 eax에 불러온다
함수의 반환 값을 and 연산하는데, 이때 문자열이 같으면 0을 플래그에 저장하게 된다
jne는 값이 0이 아닐 때 분기하는 명령어로, 문자열이 같으면 분기하지 않고 rsp+20에 1을 넣는다
이후 무조건 분기인 jmp를 만나 rsp+20에 0을 넣는 코드를 뛰어넘어 다음 코드로 진입한다
마지막으로 rsp+20에 저장한 문자열 비교 값을 eax에 넣어 함수 반환값으로 설정한다
그리고 rsp에 38을 더해서 해당 함수에서 사용한 스택을 놓고 이전에 사용하던 스택 위치로 이동한다
ret(return)으로 함수가 끝나게 된다.
즉, 이 함수에서는 오른쪽에 대놓고 나와 있는 값(Compar3_the_str1ng)을 입력값으로 들어오면
반환값으로 1을 설정해 correct를 프린트하게 만든다.
2. Ida 해석
ida는 익숙한 C언어 형태로 디컴파일해줘서 x64dbg보다 훨씬 쉽게 해석할 수 있다
위의 코드를 봐도 correct를 프린트해주는 곳의 if문만 잘 보면 해결할 수 있을 것 같다는 생각이 든다
함수의 디컴파일 버전을 보니까 x64dbg보다 훨씬 이해하기 쉬운 형태를 보여주고 있다
여기에서 strcmp(a1, "Compar3_the_str1ng")은 입력값과 문자열이 동일하면 0을 리턴한다
strcmp가 0을 리턴하게 되면 == 연산으로 0과 동일한 것을 확인하고 1을 리턴한다
정답: DH{Compar3_the_str1ng}
'dreaMhack > Reverse Engineering' 카테고리의 다른 글
[드림핵] rev_basic_4 풀이/어셈블리어 해석 (0) | 2022.03.23 |
---|---|
[드림핵] rev_basic_3 풀이/어셈블리어 해석 (0) | 2022.03.23 |
[드림핵] rev_basic_1 풀이/어셈블리어 해석 (0) | 2022.03.23 |
[드림핵] 리버싱 레지스터 용도 정리 (0) | 2022.03.23 |
[드림핵] Reverse Engineering Introduction(리버스 엔지니어링 소개) (0) | 2022.03.03 |