夜深人靜,嘿嘿
?
只有這個(gè)時(shí)候才有時(shí)間靜下來看點(diǎn)東西
前幾天在看
16
位匯編語言程序設(shè)計(jì)
?
王爽
老師寫的
?
寫得真的很好
?
呵呵
?
不是賣廣告哈
資源共享嘛
遇到一個(gè)問題
?
通過這個(gè)問題發(fā)現(xiàn)能深刻理解到
jmp
指令很具內(nèi)涵的一些內(nèi)容
甚歡
乃著此文以記之
?
程序如下:
assume
cs:codesg
codesg
segment
?? mov ax,4c00h
?? int 21h
start
:
?? mov ax,0
s:
?? nop
?? nop
?? mov di,offset s
;
這里應(yīng)該是計(jì)算
s
對(duì)于
segment
處的偏移量,賦值給
di
?? mov si,offset s2
;
計(jì)算
s2
對(duì)于
segment
處的偏移,保存到
si
?? mov ax , cs:[si]?
;
將
s
處的
1
個(gè)字節(jié)指令內(nèi)容讀入
ax
(注意,基址是
cs
哦
~
不是
ds
)
?? mov cs:[di],ax??
;
將
ax
內(nèi)容寫到
s
處,也就是填充上邊那
2
個(gè)
nop
s0:
?? jmp short s
;跳到
s
,那么這個(gè)時(shí)候位于
s
處指令應(yīng)該是
jmp s1
;接著執(zhí)行應(yīng)該是
mov ax
,
0
然后
int 21
s1:
?? mov ax,0
?? int 21h??
?? mov ax,0
s2:?
?? jmp short s1
?? nop
codesg
ends
end
start
?
?
結(jié)果發(fā)現(xiàn)我推測(cè)的跟執(zhí)行的內(nèi)容完全不一樣
……
暈厥
ING~
又過了一天
一覺醒來想了想這個(gè)結(jié)果
哈哈
恍然大悟
?
書上的例子用的是
windows
自帶的
debug
調(diào)試
……
我也只會(huì)用這個(gè)了
……
用
windbg
太麻煩
od
好像只能開
32
位的
只能截圖看了
jmp
指令在被編譯器編譯的時(shí)候會(huì)自動(dòng)計(jì)算跳轉(zhuǎn)時(shí)指針與目的地址的偏移量
然后通過加減
ip
這個(gè)數(shù)值實(shí)現(xiàn)跳轉(zhuǎn)的
也就是說
jmp s
這指令實(shí)現(xiàn)的是相對(duì)位移跳轉(zhuǎn),跳到哪那是編譯器編譯的時(shí)候就計(jì)算好的了
我們來看看
1814
:
0016
這個(gè)地方的
jmp
指令
EBF0
這個(gè)指令對(duì)應(yīng)的匯編語句應(yīng)該是
jmp s
S
是在
1814
:
0008
處
所以反編譯的結(jié)果是
jmp 0008?
沒錯(cuò)
跟我們的語句沒出入
那么我們可以看看機(jī)器碼
BEF0? BE
是
jmp
指令
F0
代表相對(duì)位移
以補(bǔ)碼形式保存
那么我們計(jì)算下發(fā)現(xiàn)
F0
對(duì)應(yīng)的
10
進(jìn)制是
-16
也就是說要往后跳
16
個(gè)字節(jié)(注意是字節(jié),
8bit
一個(gè)字節(jié)哦
~
)
1814
:
0016
這個(gè)是我們執(zhí)行到
jmp
時(shí)
cs
:
ip
的地址,也就是取指令的地址
注意這個(gè)時(shí)候我們已經(jīng)取出
jmp s
這個(gè)指令了
那么
IP
指針應(yīng)該
+2
指向
1814
:
0018
這個(gè)位置了
往后跳
16
個(gè)字節(jié)
1814
:
0018 – 10
(
10
進(jìn)制就是
16
咯)
= 1814
:
0008
應(yīng)該是跳到
0008
這個(gè)位置上了
正好就是
s
對(duì)應(yīng)的位置
那么我們看看
1814
:
0020
這個(gè)指令
EBF6? F6
是跳轉(zhuǎn)的相對(duì)位移
補(bǔ)碼形式存放
換算成
10
進(jìn)制就是
-10
想象下當(dāng)程序執(zhí)行到
s0
那個(gè)時(shí)候
s
處的那
2
個(gè)
nop
指令已經(jīng)被填充成
EBF6
了
?
根據(jù)相對(duì)位移的計(jì)算
?
這個(gè)時(shí)候程序運(yùn)行的步驟應(yīng)該是
通過
jmp s
跳轉(zhuǎn)到
1814
:
0008
地址(這個(gè)時(shí)候下一個(gè)指令對(duì)應(yīng)的機(jī)器碼是
BEF0
)
取出下一個(gè)指令
IP+2?
這個(gè)時(shí)候
IP
指向
1814
:
000a
執(zhí)行
BEF6
這個(gè)指令(向后跳
10
個(gè)字節(jié))
也就是應(yīng)該跳到
1814
:
000a
– a
(
10
的
16
進(jìn)制表示)
= 1814
:
0000
也就是說這個(gè)時(shí)候
jmp
指令應(yīng)該是
jmp 0000
跳到
segment
開始處而不是跳到
s1
處了
接著應(yīng)該是執(zhí)行
?? mov ax,4c00h
?? int 21h
實(shí)際調(diào)試的結(jié)果也是這樣的
如下圖示
?
看到?jīng)]
?
執(zhí)行
jmp 0008
也就是
jmp s
以后然后就是跳到
1814
:
0000
處
而不是跳到
s1
對(duì)應(yīng)的那個(gè)偏移處
接著就是跟我們想的一樣
執(zhí)行了
mov ax
,
4c
00h
然后就
int 21h
了
?
也就是說我們
jmp
的地址記錄的是相對(duì)偏移量
這個(gè)程序也說明了
jmp
的地址是在運(yùn)行時(shí)計(jì)算出來的而不是編譯器一開始就硬編碼進(jìn)去的
不過當(dāng)然也有硬編碼進(jìn)去的跳轉(zhuǎn)指令啦
~~
好像是
jmp
far
地址吧
忘了的說
呵呵
?
只不過小小闡明下
jmp
相對(duì)跳的執(zhí)行流程和細(xì)節(jié)部分
這樣也有個(gè)小小啟示就是以后用相對(duì)跳的時(shí)候小心咯
貌似
shellcode
編寫或者改內(nèi)核代碼的時(shí)候可以注意下
呵呵
跳轉(zhuǎn)的相對(duì)地址最好計(jì)算出來表直接就來個(gè)偏移
?
一不小心機(jī)子就當(dāng)?shù)袅?/span>
?
哇咔咔
~
?