촉촉한초코칩
[DreamHack] Quiz: x86 Assembly 2, Quiz: x86 Assembly 3 본문
Quiz: x86 Assembly 2

mov dl, BYTE PTR[rsi+rcx]
rsi + rcx = 0x400000
BYTE PTR[rsi+rcx] : rsi+rcx가 가리키는 주소에서 데이터를 1바이트 만큼 참조
dl = 0x67
xor dl, 0x30
dl = 0x57
mov BYTE PTR[rsi+rcx], dl
rsi+rcx = 0x400000
BYTE PTR[rsi+rcx] = 0x67
0x67에 dl을 넣는다는 뜻이므로 0x67값은 0x57이 된다.
inc rcx
rcx = 1
cmp rcx, 0x19
rcx의 값인 1과 0x19를 비교한다.
rcx 값이 0x19보다 크면 다음 줄을 실행하고, 크지 않으면 다시 처음으로 돌아간다. (jmp 1)
16진수인 19를 10진수로 변환하면 25이므로 처음부터 종료될 때까지 총 26번 반복한다.
파이썬 코드로 작성해보면 (^ 연산은 xor을 의미한다.)
memory = [0x67, 0x55, 0x5c, 0x53, 0x5f, 0x5d, 0x55, 0x10, 0x44,
0x5f, 0x10, 0x51, 0x43, 0x43, 0x55, 0x5d, 0x52, 0x5c,
0x49, 0x10, 0x47, 0x5f, 0x42, 0x5c, 0x54, 0x11, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00]
for i in range(26):
memory[i] = memory[i]^0x30
for c in range(26):
print(chr(memory[c]), end='')
정답 : Welcome to assembly world!
어셈블리 코드를 그대로 작성해보면 while문으로 반복해서 쓸 수 있다.
rcx = 0
memory = [0x67, 0x55, 0x5c, 0x53, 0x5f, 0x5d, 0x55, 0x10, 0x44,
0x5f, 0x10, 0x51, 0x43, 0x43, 0x55, 0x5d, 0x52, 0x5c,
0x49, 0x10, 0x47, 0x5f, 0x42, 0x5c, 0x54, 0x11, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00]
while(rcx < 26):
dl = memory[0+rcx] #0x40000은 메모리 상에서 한 줄을 뜻하기 때문에 파이썬에서 배열로 사용하려면 0을 더해준다.
dl^=0x30
memory[0+rcx] = dl
rcx+=1
for c in range(26):
print(chr(memory[c]), end="")
Quiz: x86 Assembly 3

push rbp
스택 최상단에 rbp를 넣는다. (스택 프레임을 만드는 부분)
mov rbp, rsp
* rsp : 사용중인 스택의 위치를 가리키는 포인터
* rbp : 스택의 바닥을 가리키는 포인터
→ 스택 바닥을 가리키는 곳에 사용중인 스택 위치를 대입한다.
mov esi, 0xf
mov rdi, 0x400500
rdi에 0x400500을 넣는다.
call 0x400497 <write_n>
write_n 함수 실행
push rbp
mov rbp, rsp
* rsp : 사용중인 스택의 위치를 가리키는 포인터
* rbp : 스택의 바닥을 가리키는 포인터
→ 스택 바닥을 가리키는 곳에 사용중인 스택 위치를 대입한다.
mov QWORD PTR[rbp-0x8], rdi
rdi를 rbp-0x8 위치에 8 바이트만큼 참조하여 대입한다.
rdi = 0x400500
rbp-0x8 = 0x400500
mov DWORD PTR [rbp-0xc], esi
esi의 값 중 8바이트를 rbp-0xc에 대입한다.
esi = 0xf
rbp-0xc = 0xf
xor rdx, rdx
같은 값을 xor 연산하면 0이 나온다.
rdx = 0
mov edx, DWORD PTR[rbp-0xc]
rbp - 0xc = 0xf
edx = 0xf
mov rsi, QWORD PTR[rbp-0x8]
rbp - 0x8 = 0x400500
rsi = 0x400500
mov rdi, 0x1
mov rax, 0x1
syscall
rax값이 0x1이므로 write를 호출한다.
syscall | rax | arg0 (rdi) | arg1 (rsi) | arg2 (rdx) |
write | 0x01 | unsigned int fd * 파일 디스크립터 지정 |
const char *buf * 해당 메모리에 위치한 값을 가리킨다. |
size_t count * 크기 |
rax = 0x1 > syscall 호출
rdi = 0x1 > 출력
rsi = 0x400500 > 0x3037207964343372
rdx = 0xf > 0으로 초기화한 후 mov edx, DWORD PTR [rbp-0xc] 연산으로 edx 값은 0xf가 되었다. edx는 rdx의 하위 32비트이므로 0xf가 된다. 즉 크기는 10진수인 15 바이트가 된다.
→ 0x400500에 있는 데이터 값을 15바이트 만큼 출력한다.
0x30 37 20 79 64 34 33 72 = [0x30, 0x37, 0x20, 0x79, 0x64, 0x34, 0x33, 0x72]
0x00 3f 36 75 62 33 64 20 = [0x00, 0x3f, 0x36, 0x75, 0x62, 0x33, 0x64]
→ 15바이트를 채워야 하므로 다음 주소의 값도 사용한다.
pop rbp
ret
파이썬 코드로 작성
memory = [0x30, 0x37, 0x20, 0x79, 0x64, 0x34, 0x33, 0x72,
0x00, 0x3f, 0x36, 0x75, 0x62, 0x33, 0x64]
for c in range(15):
print(chr(memory[c]), end='')
→ 07 yd43r?6ub3d
하지만 x86-64는 리틀 앤디안을 사용하기 때문에 거꾸로 읽어야 한다.
07 yd43r → r35dy 07
?6ub3d →d3bu6?
합치면 r35dy 07 d3bu6? 이 된다.
'Study > System' 카테고리의 다른 글
[Dreamhack] basic_exploitation_001 (0) | 2024.03.31 |
---|---|
[Dreamhack] basic_exploitation_000 (0) | 2024.03.31 |
[Dreamhack] Return Address Overwrite (1) | 2024.03.31 |
Bomb Lab Phase 1-3 (0) | 2024.03.24 |
시스템 스터디 정리 (0) | 2024.03.17 |