[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
cmp rcx, 0x19
이 부분을 봤을 때 rcx가 19가 되면 아래의 jg end
를 실행하고
아니라면 다시 1로 돌아가 반복하는 형태이다.
1: mov dl, BYTE PTR[rsi+rcx]
BYTE는 1바이트를 말한다.
WORD는 2바이트, DWORD라면 4바이트를 가져온다.
1바이트란 8Bit를 말하는데, 0x00로 표현할 수 있는 범위가 이에 해당된다.
그리고 PTR은 메모리 주소에 중괄호의 값을 대입에 가르키고 있는 값을 가져온다.
즉, PTR[rsi + rcx]
란 메모리에 rsi + rcx 의 주소값에 대입되어 있는 값을 가져온다는 뜻이다.
rcx = 0
rsi = 0x400000
이므로
0x400000 | 0x67 0x55 0x5c 0x53 0x5f 0x5d 0x55 0x10
여기를 가져온다는 뜻이다. 하지만 BYTE이므로 1Byte만 가져온다.
그러므로 0x67만 가져올 것이다.
dl = 0x67
xor dl, 0x30 하면
xor 0x67, 0x30
결과는 0x57, 문자로 바꾸면 W 이다.
그 후 inc rcx
를 만나 rcx는 0에서 1로 증감된다.
cmp rcx, 0x19
를 만나고 작기 때문에 다시 1로 돌아가 이를 반복한다.
0x67 xor 0x30 = 0x57(W)
0x55 xor 0x30 = 0x65(e)
0x5c xor 0x30 = 0x6c(l)
하나씩 계산기에 넣고 적기엔 너무 기니까 간단한 스크립트를 짜보자.
a = "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 a.split(" "):
print(chr(int(i,16) ^ 0x30))
0~19 까지 이므로 20개 만큼 잘라서 문자열로 넣어주고 연산해 주면 된다.
W
e
l
c
o
m
e
t
o
a
s
s
e
m
b
l
y
w
o
r
l
d
!
Welcome to assembly world!
이다.