rev-basic-4 풀이

2025. 2. 24. 17:40·Security/Reverse Engineering

문제 설명


문제 풀이(x64dbg)

문제에서 내려받은 파일을 x64dbg로 열었을 때의 모습이다. 먼저 문자열 참조 검색 기능을 사용하여 main 함수를 찾아보자.

여기서 분기문을 찾아보자. 당연히 'Correct' 문자열을 출력하는 부분 위에 있지 않겠는가?

노란 하이라이트 부분에 커서를 올려보며 cmp 명령어가 포함되었는지 확인해본다.

 

140001000에 커서를 두고 미리보기를 했을 때, cmp 명령어가 포함되어 있으니 클릭하여 들어가보자.

함수의 시작 주소가 140001000이고 ret 주소가 14000106E까지라서 살짝 길지만,,, 모든 줄을 한번 분석해보자.

 

1. mov qword ptr ss:[rsp+8],rcx : rcx(첫번째 함수 인자)값을 rsp+8(스택)에 저장

2. sub rsp,18 : rsp 값을 0x18(24)만큼 감소시켜 스택 프레임 확보

3. mov dword ptr ss:[rsp],0 : rsp가 가리키는 메모리를 0으로 초기화

4. jmp chall4.14000101A : 14000101A로 jump 

5. mov eax,dword ptr ss:[rsp] : [rsp]를 eax에 넣기(초기값은 0)

6. inc eax : eax++

7. mov dword ptr ss:[rsp],eax : 증가된 eax 값을 다시 [rsp]에 저장

8. movsxd rax,dword ptr ss:[rsp] : 길이가 일치하지 않아도 rsp값을 rax로 이동

9. cmp rax,1C : rax와 1C(10진수로 28) 비교

10. jae chall4.140001065 : 결과가 크거나 같으면 즉, rax >= 0x1C라면 반복문 종료

11. movsxd rax,dword ptr ss:[rsp] : 길이가 일치하지 않아도 rsp값을 rax로 이동

12. mov rcx,qword ptr ss:[rsp+20] : rcx = [rsp + 20]

13. movzx eax,byte ptr ds:[rcx+rax] : eax = *(rcx + rax) 즉, rcx가 가리키는 문자열의 rax번째 문자를 가져옴

14. sar eax,4 : eax 값을 오른쪽으로 4비트 shift(상위 4비트만 유지)

15. movsxd rcx,dword ptr ss:[rsp] : rsp값을 rcx로 변환

16. mov rdx,qword ptr ss:[rsp+20] = rdx = [rsp + 20]

17. movzx ecx,byte ptr ds:[rdx+rcx] : ecx = *(rdx + rcx) 즉, rdx가 가리키는 문자열의 rcx번째 문자를 ecx에 저장

18. shl ecx,4 : ecx값을 왼쪽으로 4비트 shift(하위 4비트는 모두 0이 된다)

19.  and ecx,F0 : ecx의 하위 4비트를 0으로 유지

20. or eax,ecx : eax |= ecx 즉, 상위 4비트와 하위 4비트를 결합

21. movsxd rcx,dword ptr ss:[rsp] : rsp값을 rcx로 변환

22. lea rdx,qword ptr ds:[140003000] : rdx에 특정 메모리 주소 0x140003000 로드(비교용 데이터)

23. movzx ecx,byte ptr ds:[rdx+rcx] : ecx = *(rdx + rcx) 즉, 비교 대상 문자 가져오기

24. cmp eax,ecx : eax와 ecx 비교

25. je chall4.140001063 : 값이 같으면 140001063으로 jump, 루프 반복

26. xor eax,eax : eax값을 0으로 초기화(비교 실패 시)

27. jmp chall4.14000106A : 14000106A로 점프(종료)

28. jmp chall4.140001012 : 140001012로 점프(루프 재실행)

29. mov eax,1 : eax = 1(성공 플래그 설정)

30. add rsp,18 : rsp 원래대로 복구

31. ret : 함수 종료 및 반환

 

여기서 우리가 눈여겨봐야 할 부분은 문자열 비교를 수행하는 11번째 줄부터 20번째 줄까지이다.

이를 간단히 나타내면 다음과 같은 식이 나온다.

 

140003000번_주소의_값[i] >> 4 |  140003000번_주소의_값[i] << 4 

 = 상위 4비트를 하위 4비트로 이동 | 하위 4비트를 상위 4비트로 이동

 

결국, 140003000번 주소로부터 28개의 문자들의 상위 4비트를 하위 4비트로, 하위 4비트를 상위 4비트로 이동시키면 FLAG를 얻을 수 있다는 것이다. 

 

덤프창에서 140003000번 주소가 가리키는 문자들은 다음과 같다.

 

140003000번부터 28개의 문자를 16진수로 나타낸 값은 다음과 같다.

 

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

 

이를 역순으로 계산하여 FLAG 값을 찾아보자.

0x24 : 0x2 >> 4 | 0x4 << 4 = 0x42 = 66 = 'B'  
0x27 : 0x2 >> 4 | 0x7 << 4 = 0x72 = 114 = 'r'  
0x13 : 0x1 >> 4 | 0x3 << 4 = 0x31 = 49 = '1'  
0xC6 : 0xC >> 4 | 0x6 << 4 = 0x6C = 108 = 'l'  
0xC6 : 0xC >> 4 | 0x6 << 4 = 0x6C = 108 = 'l'  
0x13 : 0x1 >> 4 | 0x3 << 4 = 0x31 = 49 = '1'  
0x16 : 0x1 >> 4 | 0x6 << 4 = 0x61 = 97 = 'a'  
0xE6 : 0xE >> 4 | 0x6 << 4 = 0x6E = 110 = 'n'  
0x47 : 0x4 >> 4 | 0x7 << 4 = 0x74 = 116 = 't'  
0xF5 : 0xF >> 4 | 0x5 << 4 = 0x5F = 95 = '_'  
0x26 : 0x2 >> 4 | 0x6 << 4 = 0x62 = 98 = 'b'  
0x96 : 0x9 >> 4 | 0x6 << 4 = 0x69 = 105 = 'i'  
0x47 : 0x4 >> 4 | 0x7 << 4 = 0x74 = 116 = 't'  
0xF5 : 0xF >> 4 | 0x5 << 4 = 0x5F = 95 = '_'  
0x46 : 0x4 >> 4 | 0x6 << 4 = 0x64 = 100 = 'd'  
0x27 : 0x2 >> 4 | 0x7 << 4 = 0x72 = 114 = 'r'  
0x13 : 0x1 >> 4 | 0x3 << 4 = 0x31 = 49 = '1'  
0x26 : 0x2 >> 4 | 0x6 << 4 = 0x62 = 98 = 'b'  
0x26 : 0x2 >> 4 | 0x6 << 4 = 0x62 = 98 = 'b'  
0xC6 : 0xC >> 4 | 0x6 << 4 = 0x6C = 108 = 'l'  
0x56 : 0x5 >> 4 | 0x6 << 4 = 0x65 = 101 = 'e'  
0xF5 : 0xF >> 4 | 0x5 << 4 = 0x5F = 95 = '_'  
0xC3 : 0xC >> 4 | 0x3 << 4 = 0x3C = 60 = '<'  
0xC3 : 0xC >> 4 | 0x3 << 4 = 0x3C = 60 = '<'  
0xF5 : 0xF >> 4 | 0x5 << 4 = 0x5F = 95 = '_'  
0xE3 : 0xE >> 4 | 0x3 << 4 = 0x3E = 62 = '>'  
0xE3 : 0xE >> 4 | 0x3 << 4 = 0x3E = 62 = '>'

 

따라서 FLAG는

Brl1ll1ant_bit_drlbble_<<_>>

 

라고 구할 수 있다.


문제 풀이(IDA)

문제 파일을 IDA로 열면 다음과 같은 화면이 나온다.

바로 디컴파일 기능을 사용해보자.

여기서 비교 연산을 수행하는 sub_140001000 메소드를 클릭하면 다음과 같은 코드가 나온다.

이를 조금 쉬운 코드로 바꿔서 FLAG 값을 구해보자.

byte_140003000 = [
    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
]

a1 = []
for b in byte_140003000:
    high = b >> 4 
    low = b & 0xF
    a1.append((low << 4) | high)

print(a1)

 

FLAG : 

Brl1ll1ant_bit_drlbble_<<_>>

'Security > Reverse Engineering' 카테고리의 다른 글

rev-basic-7 풀이  (0) 2025.02.28
rev-basic-5 풀이  (0) 2025.02.24
rev-basic-6 풀이  (0) 2025.02.23
rev-basic-3 풀이(IDA)  (0) 2025.02.20
rev-basic-3 풀이  (0) 2025.02.05
'Security/Reverse Engineering' 카테고리의 다른 글
  • rev-basic-7 풀이
  • rev-basic-5 풀이
  • rev-basic-6 풀이
  • rev-basic-3 풀이(IDA)
switch_user
switch_user
나의 공부 기록
  • switch_user
    while(true)
    switch_user
  • 전체
    오늘
    어제
    • 분류 전체보기
      • C
      • C++
      • Java
      • Python
      • Web
      • App
      • Security
        • Web Hacking
        • Reverse Engineering
      • DB
      • Machine Learning
      • Computer Science
      • Linux
      • Algorithm
      • 진로
      • 기타
  • 블로그 메뉴

    • 홈
    • 태그
    • velog
    • Github
  • 링크

    • velog
    • Github
  • 공지사항

  • 인기 글

  • 태그

    Web 기초
    인터프리팅
    SQLi
    IDA
    쿠키
    웹
    xss
    사례 기반 학습
    HTML
    비트연산
    머신러닝
    CSS
    클래스 외부에 함수 구현
    cin.getline
    모델 기반 학습
    웹해킹
    반복문
    ml
    생성자와 소멸자
    Hacking Process
    race condition
    SQL
    코드 패치
    HTTP
    어셈블리어
    디컴파일
    x64dbg
    배치 학습
    어셈블리
    리버싱
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
switch_user
rev-basic-4 풀이
상단으로

티스토리툴바