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