발자취

[Reverse Engineering] #05-2. 어셈블리어와 x86-64 - Quiz 본문

Dreamhack Study/Reverse Engineering

[Reverse Engineering] #05-2. 어셈블리어와 x86-64 - Quiz

해린 2024. 5. 30. 00:58

본 게시물은 Dreamhack의 Reverse Engineering 로드맵 과정을 학습한 기록이다.

 

#01. Quiz: x86 Assembly 1

Q1. 레지스터, 메모리 및 코드가 다음과 같다. Code를 1까지 실행했을 때, rax에 저장된 값은?
[Register]
rbx = 0x401A40

=================================

[Memory]
0x401a40 | 0x0000000012345678
0x401a48 | 0x0000000000C0FFEE
0x401a50 | 0x00000000DEADBEEF
0x401a58 | 0x00000000CAFEBABE
0x401a60 | 0x0000000087654321

=================================

[Code]
1: mov rax, [rbx+8]
2: lea rax, [rbx+8]
  1. 0x87654321
  2. 0xC0FFEE
  3. 0xCAFEBABE
  4. 0x12345678
  5. 0xDEADBEEF

답: 2

 

Q2. Code를 2까지 실행했을 때, rax에 들어있는 값은?
[Register]
rbx = 0x401A40

=================================

[Memory]
0x401a40 | 0x0000000012345678
0x401a48 | 0x0000000000C0FFEE
0x401a50 | 0x00000000DEADBEEF
0x401a58 | 0x00000000CAFEBABE
0x401a60 | 0x0000000087654321

=================================

[Code]
1: mov rax, [rbx+8]
2: lea rax, [rbx+8]​
  1. 0x401A40
  2. 0x12345680
  3. 0x00C0FFF6
  4. 0x401A48
  5. 0x00C0FFEE

답: 4

 

 

Q3. 레지스터, 메모리 및 코드가 다음과 같다. Code를 1까지 실행했을 때, rax에 저장된 값은?

[Register]
rax = 0x31337
rbx = 0x555555554000
rcx = 0x2

=================================

[Memory]
0x555555554000| 0x0000000000000000
0x555555554008| 0x0000000000000001
0x555555554010| 0x0000000000000003
0x555555554018| 0x0000000000000005
0x555555554020| 0x000000000003133A

==================================

[Code]
1: add rax, [rbx+rcx*8]
2: add rcx, 2
3: sub rax, [rbx+rcx*8]
4: inc rax
  1. 0x31336
  2. 0x31337
  3. 0x31338
  4. 0x3133A
  5. 0x31339

답: 4

 

해설:

우선 주소 계산부터 해보자면, 

  • rbx = 0x555555554000
  • rcx = 0x2 (10진수로 2)
  • 0x2 * 8 = 16 (10진수) = 0x10 (16진수)

→ rbx + 0x10 = 0x555555554010

 

[0x555555554010] 주소에 있는 값은 0x3이다.

 

rax는 0x31337이므로

rax에 0x3을 더하면, 0x3133A가 된다!

 

 

Q4. Code를 3까지 실행했을 때, rax에 저장된 값은?
[Register]
rax = 0x31337
rbx = 0x555555554000
rcx = 0x2

=================================

[Memory]
0x555555554000| 0x0000000000000000
0x555555554008| 0x0000000000000001
0x555555554010| 0x0000000000000003
0x555555554018| 0x0000000000000005
0x555555554020| 0x000000000003133A

==================================

[Code]
1: add rax, [rbx+rcx*8]
2: add rcx, 2
3: sub rax, [rbx+rcx*8]
4: inc rax
  1. 2
  2. 0x31337
  3. 0
  4. 1
  5. 0x31338

 

답: 3

 

해설: 

Code 1) rax = 3133A

Code 2) rcx = 0x4

Code 3) 

rbx+rcx*8 = 0x555555554000 + 0x4 * 8 = 0x555555554000 + 0x20 (10진수로 32) = 0x555555554020

[rbx+rcx*8] 주소에 있는 값은 0x3133A

rax에서 0x3133A를 빼면 0이 된다

 

 

Q5. Code를 4까지 실행했을 때, rax에 저장된 값은?
[Register]
rax = 0x31337
rbx = 0x555555554000
rcx = 0x2

=================================

[Memory]
0x555555554000| 0x0000000000000000
0x555555554008| 0x0000000000000001
0x555555554010| 0x0000000000000003
0x555555554018| 0x0000000000000005
0x555555554020| 0x000000000003133A

==================================

[Code]
1: add rax, [rbx+rcx*8]
2: add rcx, 2
3: sub rax, [rbx+rcx*8]
4: inc rax
  1. 0x3133A
  2. 4
  3. 0
  4. 0x31338
  5. 1

답: 5

 

해설: Code 3까지 실행했을 때 rax는 0이었고, inc는 +1 해주는 명령어이므로 1이 된다

 

 

Q6. 레지스터, 메모리 및 코드가 다음과 같다. Code를 1까지 실행했을 때, rax에 저장된 값은?
[Register]
rax = 0xffffffff00000000
rbx = 0x00000000ffffffff
rcx = 0x123456789abcdef0

==================================

[Code]
1: and rax, rcx
2: and rbx, rcx
3: or rax, rbx
  1. 0x0000000000000000
  2. 0x1234567800000000
  3. 0x9ABCEDF000000000
  4. 0x000000009ABCDEF0
  5. 0x0000000012345678

답: 2

 

해설:

f and 1 = 1

f and 2 = 2

.

.

.

0 and a = 0

 

 

Q7. Code를 2까지 실행했을 때, rbx에 저장된 값은?
[Register]
rax = 0xffffffff00000000
rbx = 0x00000000ffffffff
rcx = 0x123456789abcdef0

==================================

[Code]
1: and rax, rcx
2: and rbx, rcx
3: or rax, rbx
  1. 0x9ABCEDF000000000
  2. 0x1234567800000000
  3. 0x0000000012345678
  4. 0x000000009ABCDEF0
  5. 0x00000000FFFFFFFF

답: 4

 

 

Q8. Code를 3까지 실행했을 때, rax에 저장된 값은?
[Register]
rax = 0xffffffff00000000
rbx = 0x00000000ffffffff
rcx = 0x123456789abcdef0

==================================

[Code]
1: and rax, rcx
2: and rbx, rcx
3: or rax, rbx
  1. 0x0000000012345678
  2. 0x9ABCDEF012345678
  3. 0x123456789ABCDEF0
  4. 0xFFFFFFFF00000000
  5. 0x1234567800000000

답: 3

 

 

Q9. 레지스터, 메모리 및 코드가 다음과 같다. Code를 1까지 실행했을 때, rax에 저장된 값은?
[Register]
rax = 0x35014541
rbx = 0xdeadbeef

==================================

[Code]
1: xor rax, rbx
2: xor rax, rbx
3: not eax
  1. 0xEBACFBAE
  2. 0xDEADBEEF
  3. 0xBAADF00D
  4. 0xCAFEBABE
  5. 0x35014541

답: 1

 

해설:

(64비트 바이너리 형태)

rax: 00000000000000000000000000110101000001000001010101000001
rbx: 00000000000000000000000011011110101011011011111011101111
----------------------------------------------------------------
xor: 00000000000000000000000011101011101010011010101110101110

 

(16진수)

0xebaeebae

 

 

Q10. Code를 2까지 실행했을 때, rax에 저장된 값은?
[Register]
rax = 0x35014541
rbx = 0xdeadbeef

==================================

[Code]
1: xor rax, rbx
2: xor rax, rbx
3: not eax​
  1. 0xDEADBEEF
  2. 0xFACEFEED
  3. 0xCAFEBABE
  4. 0x35014541
  5. 0xBAADF00D

답: 4

 

 

Q11. Code를 3까지 실행했을 때, rax에 저장된 값은?
[Register]
rax = 0x35014541
rbx = 0xdeadbeef

==================================

[Code]
1: xor rax, rbx
2: xor rax, rbx
3: not eax
  1. 0xDEADD00D
  2. 0xCAFEBABE
  3. 0xDEADBEEF
  4. 0x35014541
  5. 0xBAADF00D

답: 2

 

 

Q12. end로 점프하면 프로그램이 종료된다고 가정하자. 프로그램이 종료됐을 때, 0x400000 부터 0x400019까지의 데이터를 대응되는 아스키 문자로 변환하면?
[Register]
rcx = 0
rdx = 0
rsi = 0x400000

=======================

[Memory]
0x400000 | 0x67 0x55 0x5c 0x53 0x5f 0x5d 0x55 0x10
0x400008 | 0x44 0x5f 0x10 0x51 0x43 0x43 0x55 0x5d
0x400010 | 0x52 0x5c 0x49 0x10 0x47 0x5f 0x42 0x5c
0x400018 | 0x54 0x11 0x00 0x00 0x00 0x00 0x00 0x00

=======================

[code]
1: mov dl, BYTE PTR[rsi+rcx]
2: xor dl, 0x30
3: mov BYTE PTR[rsi+rcx], dl
4: inc rcx
5: cmp rcx, 0x19
6: jg end
7: jmp 1
참고)

아스키 테이블: https://ko.wikipedia.org/wiki/ASCII
파이썬 아스키 변환: https://docs.python.org/3/library/functions.html#chr​
  1. Welcome to computer world!
  2. Welcome to assembly world!
  3. We1come to ass3mbly w0rld!
  4. Welcome t0 assembly world!
  5. W31c0m3 t0 4553mb1y w0r1d!

답: 2

 

 


#01. Quiz: x86 Assembly 2

Q1. end로 점프하면 프로그램이 종료된다고 가정하자. 프로그램이 종료됐을 때, 0x400000 부터 0x400019까지의 데이터를 대응되는 아스키 문자로 변환하면 어느 문자열이 나오는가?
[Register]
rcx = 0
rdx = 0
rsi = 0x400000
=======================
[Memory]
0x400000 | 0x67 0x55 0x5c 0x53 0x5f 0x5d 0x55 0x10
0x400008 | 0x44 0x5f 0x10 0x51 0x43 0x43 0x55 0x5d
0x400010 | 0x52 0x5c 0x49 0x10 0x47 0x5f 0x42 0x5c
0x400018 | 0x54 0x11 0x00 0x00 0x00 0x00 0x00 0x00
=======================
[code]
1: mov dl, BYTE PTR[rsi+rcx]
2: xor dl, 0x30
3: mov BYTE PTR[rsi+rcx], dl
4: inc rcx
5: cmp rcx, 0x19
6: jg end
7: jmp 1

답: Welcome to assembly world!

 

해석: 

Code 1) BYTE PTR[rsi+rcx] 값은 0x400000값의 0x67이므로, dl = 0x67

Code 2) dl와 0x30를 xor 연산해보면 0x57이 나온다.Code 3) BYTE PTR[rsi+rcx]에 이 0x51 값을 대입한다.Code 4) rcx의 값에 1을 더한다 (rcx = 1)Code 5) rcx와 0x19를 비교했을 때,Code 6) rcx가 더 크다면 end로 점프한다Code 7) rcx가 더 크지 않다면 Code 1로 점프하여 이 과정을 계속 반복한다.

 

이러한 과정을 반복하며 계산해보면 "Welcome to assembly world!"라는 문구가 나온다.

 


#03. Quiz: x86 Assembly 3

Q1. 다음 어셈블리 코드를 실행했을 때 출력되는 결과로 올바른 것은?
[Code]
main:
    push rbp
    mov rbp, rsp
    mov esi, 0xf
    mov rdi, 0x400500
    call 0x400497 <write_n>
    mov eax, 0x0
    pop rbp
    ret
    
write_n:
    push rbp
    mov rbp, rsp
    mov QWORD PTR [rbp-0x8],rdi
    mov DWORD PTR [rbp-0xc],esi
    xor rdx, rdx
    mov edx, DWORD PTR [rbp-0xc]
    mov rsi,QWORD PTR [rbp-0x8]
    mov rdi, 0x1
    mov rax, 0x1
    syscall
    pop rbp
    ret
    
==================================    
[Memory]
0x400500 | 0x3037207964343372
0x400508 | 0x003f367562336420
  1. r34dy 70 d3bu6?
  2. are you ready to debug?
  3. ready to debug?
  4. 4r3 y0u r34dy 70 d3bu6?

답: 1

 

해설:

main: 

1. rbp를 스택 최상단에 push

2. rbp = rsi

3. esi = 0xf

4. rdi = 0x400500

5. write_n 함수 실행

 

write_n: 

1. rbp를 스택 최상단에 push

2. rbp = rsi

3. QWORD PTR [rbp-0x8] = 0x400500

4. DWORD PTR [rbp-0xc] = 0xf

5. rdx = 0

6. edx = 0xf

7. rsi = 0x400500

8. rdi = 0x1

9. rax = 0x1

10. system call

11. rbp(스택 최상단값) pop

12. write_n에서 나가 main 함수의 call 함수 다음 줄로 감

 

main:

6. eax = 0x0

7. rbp(스택 최상단값) pop

8. 끝

 

Code를 모두 실행하고 나서도 Memory 값에는 변함이 없다

따라서 처음에 주어졌던 Memory 값을 아스키값으로 변환해주면 된다.

(이때 리틀 엔디안 방식으로 표기되어 있다는 것을 주의하고 오른쪽에서부터 읽어줘야 한다.)

 


참고 게시글

https://predic.tistory.com/105

 

드림핵 Quiz: x86 Assembly 3 풀이

[Code] main: push rbp mov rbp, rsp mov esi, 0xf mov rdi, 0x400500 call 0x400497 mov eax, 0x0 pop rbp ret write_n: push rbp mov rbp, rsp mov QWORD PTR [rbp-0x8],rdi mov DWORD PTR [rbp-0xc],esi xor rdx, rdx mov edx, DWORD PTR [rbp-0xc] mov rsi,QWORD PTR [rbp

predic.tistory.com