小華的部落格: 組合語言Assembly

搜尋此網誌

網頁

顯示具有 組合語言Assembly 標籤的文章。 顯示所有文章
顯示具有 組合語言Assembly 標籤的文章。 顯示所有文章

星期三, 9月 11, 2013

一個關於INT 3h的知識分享

恩,好久沒來發文章了!  慢慢地最近比較有時間,所以會在寫些文章分享一下知識!

-----------------------------------------------------------------------------------------------------------------

一個關於INT 3h的知識分享

一般來說INT xxh的機器碼會看到是CD imm8 ,例如: CD 19 就是呼叫INT 19h.

而INT3比較特別,他有一個1 byte的OPCODE是0xCC,使用1個BYTE的好處是"他可以覆蓋在任何指令的第一個BYTE而不會去破壞掉原本的指令意思"

而2 bytes的方式就沒這個好處! 如果你了解INTEL 指令,你就會知道一行指令是由Prefix OPCODE.......部分組成的,所以一行指令所代表的機器碼長度不同,因此一個Byte的INT 3h就可以利用這些特性讓Debugger去插入INT 3h的斷點,然後跳到Debug Engine裡面.


底下是範例代碼,一個換掉原本位置的方式:

    lds      bx,BreakToAddress  ;Insert INT3h OPCODE to this addrees
    mov    al,0CCh                  ;INT 03h opcode 
    xchg   [bx],al                    ;Set INT 3h OPCODE and also save original opcode into AL          

    mov    OriginalOpCode,al   ;Save  original opcode 
  

星期二, 3月 23, 2010

64 bit 組合語言

64 bit 組合語言需要注意事項:

1.多了一些64 bit暫存器
r8,r9,r10,r11,r12,r13,r14,r15

2.暫存器長度變成64 bit
rax,rbx,rcx,rdx,rsi,rdi,rsp,rbp

3.堆疊操作指令要對應64 bit暫存器
ex: (Push, pop, call, ret, enter, and leave) push eax;這是非法的
push rax;這是合法的

4.RIP變成合法化來存取資料
mov,rax,qword ptr [rip+300];以前IP只能當成程式記數器,現在可以參與資料獲取 也因此在64 bit下,DS/ES/SS/CS變的很沒有意義了!

5.Calling Conventions (呼叫慣例)變成Callee(被呼叫者)不需要清除Stack,這是Caller呼叫者的工作

EX:
Function(arg1,arg2,arg3,arg4,arg5) ,假設arg1~4都是整數,他們分別會被放進去對應的暫存器
RCX: 1st integer arg
RDX: 2nd integer arg
R8: 3rd integer arg
R9: 4th integer arg

arg5才會被放進去Stack,但是這個stack會先幫這幾個arg預留空間,
所以第5個參數會是放在 rsp+0x20的地方!

這個概念跟我們以前32 bit觀念不同,他並不是__cdecl/ __stdcall/ __fastcall
所以從下面的範例中可以看到呼叫者會去清除stack:

The stack must be kept 16-byte aligned. Since the "call" instruction
pushes an 8-byte return address, this means that every non-leaf
function is going to adjust the stack by a value of the form 16n+8 in
order to restore 16-byte alignment.

ex:
void SomeFunction(int a, int b, int c, int d, int e);
void CallThatFunction()
{
SomeFunction(1, 2, 3, 4, 5);
SomeFunction(6, 7, 8, 9, 10);
}

On entry to CallThatFunction, the stack looks like this:
xxxxxxx0 .. rest of stack ..
xxxxxxx8 return address <- RSP

Due to the presence of the return address, the stack is misaligned. CallThatFunction sets up its stack frame, which might go like this:

    sub    rsp, 0x28

Notice that the local stack frame size is 16n+8, so that the result is a realigned stack.

xxxxxxx0 .. rest of stack ..
xxxxxxx8 return address
xxxxxxx0
(arg5)
xxxxxxx8
(arg4 spill)
xxxxxxx0
(arg3 spill)
xxxxxxx8
(arg2 spill)
xxxxxxx0
(arg1 spill) <- RSP

Now we can set up for the first call:

        mov     dword ptr [rsp+0x20], 5     ; output parameter 5
mov r9d, 4 ; output parameter 4
mov r8d, 3 ; output parameter 3
mov rdx, 2 ; output parameter 2
mov rcx, 1 ; output parameter 1
call SomeFunction ; Go Speed Racer!

When SomeFunction returns, the stack is not cleaned, so it still looks like it did above. To issue the second call, then, we just shove the new values into the space we already reserved:

        mov     dword ptr [rsp+0x20], 10    ; output parameter 5
mov r9d, 9 ; output parameter 4
mov r8d, 8 ; output parameter 3
mov rdx, 7 ; output parameter 2
mov rcx, 6 ; output parameter 1
call SomeFunction ; Go Speed Racer!
CallThatFunction is now finished and can clean its stack and return.
        add     rsp, 0x28
ret

Notice that you see very few "push" instructions in amd64 code, since the paradigm is for the caller to reserve parameter space and keep re-using it.

這種呼叫慣例比較像是結合了__cdecl/ __fastcall 的特性:
__cdecl : 在呼叫者(Callee) return,由呼叫者(Caller)清除堆疊
__fastcall : 32bit時是將最左邊兩個參數會放在ecx跟edx ,而64 bit 這邊是放在rcx,rdx,r8,r9

Reference
http://blogs.msdn.com/oldnewthing/archive/2004/01/14/58579.aspx

星期一, 5月 07, 2007

SEGMENT與Public/Extern 用法

在BIOS Source code之中常常會看到一大堆的Segment,而有時候相同的Segment內去使用同一個Segment內的程序時,會在Segment 內去把他Extern進來,如下範例所示:

Test1.asm
AAA SEGMENT <--AAA Segment 裡面有一個BBB程序被共用(Public)
....
BBB PROC NEAR PUBLIC
...
BBB ENDP
....
AAA ENDS

Test2.asm內容如下
AAA SEGMENT <--AAA Segment內有一個CCC程序要去呼叫BBB程序,但是要在AAA Segment把BBB程式用Extern方式拉進來
EXTERN BBB:NEAR
....
CCC PROC
...
CALL BBB
...
CCC ENDP
AAA ENDS

Public 是把程序共用,而Extern 可看作要使用一個共用的程序
一般來說如果BBB程序與CCC程序都在同一個檔案內,那麼CCC程序可以直接呼叫BBB程序而不需要Extern
而不同"檔案"時就要這樣做,如上面範例是Test1.asm 跟Test2.asm

Strong/Weak 語法與"::"標籤表示法

組合語言中的Strong/Weak 語法簡單說就是如果A存在就跳躍過去A執行,如果A不存在就跳到B去執行
假如我有一段程式如下面所示:

PUBLIC BBB&Return
EXTERN AAA(BBB&Return):NEAR <--Strong/weak寫法

Test1 Proc
...
Jmp AAA
...
BBB&Return:: <--如果AAA不存在會跳到這邊執行
ret
Test1 EndP

AAA Proc <--如果AAA存在會跳到這邊執行
...
ret
AAA EndP

除了上面的Strong/Weak之外,還可以看到標籤是BBB&Return:: 而"::"代表的意思有兩種:
1.PUBLIC 出來的標籤,要把它標示成"::",簡單說就是不同程序間也可以跳躍
2."::"不同程序間的跳躍,如下面範例所示:
[註]功能還是跟 ":"一樣,只是表示方式不同而已。

Public Label2
Test1 proc near

Label1:

Label2::

ret
Test1 endp

Test2 proc near

jmp Label1 ; compiler 會錯誤, 因為該 label 找不到

jmp Label2 ; 正確, 該 label2 是可以找到的,因為有把他Public

ret
Test2 endp