본문 바로가기
Computer Science/language

[assembly | dreamhack] - Quiz: x86 Assembly 2 writeup

by yeong-yi 2025. 5. 25.
Contents

Q1. end로 점프하면 프로그램이 종료된다고 가정하자. 프로그램이 종료됐을 때, 0x400000부터 0x400019까지의 데이터를 대응되는 아스키 문자로 변환하면 어느 문자열이 나오는가?

 

end로 점프하며 프로그램이 종료된 시점에 데이터가 어떻게 바뀌었을 지를 알아내야 하는 문제이다.

 

레지스터 설명

  • rcx: 반복 횟수를 제어하는 카운터 역할이다. 초기값은 0이다.
  • rsi: 데이터의 시작 주소를 담고 있다. (예시에선 0x400000)
  • dl: rdx의 하위 8비트이다. 1바이트 데이터를 임시 저장하기 위해 사용된다.

코드 설명

 

5~6행

[code]의 6행을 확인하면 jg end라는 코드를 볼 수 있다.

jg 명령어는 jump if greater라는 뜻으로 직전에 비교한 두 피연산자 중 전자가 더 크면 주어진 주소로 jump 한다.

 

그 위 명령어를 확인하면 cmp rcx, 0x19이다.

rcx에 들어있는 값과 0x19를 비교한다.

 

-->

따라서 rcx에 들어있는 값이 0x19보다 크다면 end로 점프하고, 그때 프로그램이 종료됨을 알 수 있다.

rcx에 들어있는 값이 0x19보다 크지 않다면 7행의 jmp 1이 실행되어 다시 코드의 처음으로 돌아간다.

--> 즉!! rcx의 값이 0x19보다 작을 동안 1~7행이 반복됨을 알 수 있다.

 

7행

jmp 1 명령어는 1행으로 jump(돌아가라는 뜻)해야 한다.

 

1행

mov dl, BYTE PTR[rsi+rcx]는 메모리 주소 [rsi+rcx]에서 1바이트를 읽어와 dl에 저장한다. 즉 메모리에서 데이터를 읽어오는 과정이 된다.

rsi는 0x400000이고, rcx는 0이므로 [0x400000] 주소에서 1바이트만큼의 데이터를 dl로 옮기면 dl에는 0x67이 저장된다.

 

2행 

xor dl, 0x30은 dl에 저장된 1바이트 값(0x67)과 0x30은 ASCII로 '0'에 해당하는 값이다. 연산 결과 0x57이 새로 저장된다.

 

3행

mov BYTE PTR[rsi+rcx], dl은 XOR 연산으로 변경된 값을 원래 주소에 다시 저장한다. -> 원본 데이터에 결과값을 덮어쓰기 하는 것이다.

 

4행

inc rcx 명령어는 inc는 +1 하는 명령어이다. rcx 값을 1 증가 시킨다. => 루프를 위한 카운터를 증가시킨다.

 

이런식으로 코드가 돌아간다.

결국 rcx는 0x19를 아스키 코드로 변환한 26을 넘기기 전까지 1~6행을 반복하게 됨으로 26회 반복 수행 한다.

문자열은 25바이트의 문자열이 나오게 될 것이며 문자열은 각 연산 값으로 채워지게 된다.

 

연산 결과: Welcome to assembly world!

 

이 어셈블리 루틴은 전형적인 XOR 디코딩 루프이다.

보안 관점에서 간단한 문자열 난독화나 정적 분석 방지를 위해 종종 사용된다.