Author: Benina
My blog: rootbiez.tk
Download : [source]
Bài viết tóm tắt cách tạo 1 dll trong tasm32. Ở đây ko nói về lý thuyết dll. Bài này chỉ là một bài thực hành. Tôi viết chỉ để lưu trữ cho riêng tôi.
Một dll cơ bản như sau:
1: .586p
2: .model flat, stdcall
3: locals
4: jumps
5:
6: include c:\tasm32\include\shitheap.inc
7: include dll.inc
8: include struct.inc
9:
10: .data
11: String1 db "kernel32.dll", 0
12: hmodule dd ?
13:
14: .code
15: ;dllmain, entrypoint dll
16: start proc
17: arg imagebase
18: arg reason
19: arg reserved
20:
21: pushad
22: cmp reason, 1
23: jne __e_dllinit
24:
25: ;(code here)
26:
27: __e_dllinit: popad
28: mov eax, 1
29: leave
30: retn 0ch
31: endp
32:
33: public my_Function
34: my_Function:
35: ;code my func to export
36: Retn
37:
38: end start
39:
0/Header file:
1: .586p
2: .model flat, stdcall
3: locals
4: jumps
.586p :Dùng các chỉ thị của bộ vi xử lý 586p trở lên
.model flat, stdcall : Bộ nhớ dùng flat memory model. Và quy ước gọi hàm là stdcall
jumps : Làm cho TASM tìm ra vị trí của một lệnh nhảy có điều kiện.
locals : Cho phép block-scoped symbols
1/Giá trị trả về của dllmain retn 0ch:
Phần khởi trị đầu tại entry point của chương trình của bạn phải quite với một chỉ lệnh ret 0Ch và ko exit với ExitProcess như file exe. Lý do đơn giản là loader gọi entry point gống như sau:
1: BOOL WINAPI DllEntryPoint(
2: HINSTANCE hinstDLL, // handle of DLL module
3: DWORD fdwReason, // reason for calling function
4: LPVOID lpvReserved // reserved
5: );
Nói một chút về lệnh RETN: Lệnh “RETN 4” có nghĩa là chuyển điều khiển EIP đến [esp+4] tức là sẽ bỏ qua 4 bytes addr trên stack để lấy addr cho EIP tại esp+4.
Chúng ta chú ý:
Ta có 4 tham số cho hàm proc của dll:
arg imagebase
arg reason
arg reserved
Vì vậy theo như lệnh retn nói trên chúng ta sẽ trả về : retn 0ch
2/Tham số reason:
Có các giá trị sau:
Setting Value Description
DLL_PROCESS_ATTACH 1 New process has started
DLL_THREAD_ATTACH 2 New thread has been created
DLL_THREAD_DETACH 3 Thread is about to be terminated
DLL_PROCESS_DETACH 0 Process is about to terminate
DLL đụoc gọi khi nó bị gắn vào process hay thread hay khi nó tách ra từ một process hay thread. Do đó tham số reason sẽ có các giá trị trên
3/Exported func được viết như sau:
public myFunction
myFunction PROC
; your code goes here ...
ret
myFunction ENDP
Hay
public my_Function
my_Function:
;code my func to export
Retn
Nếu bạn ko hai báo func của bạn là publuc thì linker sẽ cho bạn cảnh báo.
4/Bảo quản thanh ghi:
Vài thanh ghi phải được bảo quản trong DLL entrypoint của chúng ta. Điều này rất quan trọng, nếu bạn ko bảo quản (preserve) chúng thì process loaded DLL sẽ kết thúc mà ko đưa ra thông báo lỗi gì sau khi DLL entrypoint đã run. Tôi ko biết những thanh ghi gì được bảo quản, nhưng ESI là chắc chắn. Một cách tốt nhất là dùng PUSHAD và POPAD để bảo quản tất cả các thanh ghi. Giá trị trả về chỉ quan trọng khi entrypoint được gọi với giá trị DLL_PROCESS_ATTACH cho tham số reason. Nó phải khác zero vì mục đích là đề xuất với hàm LoadLibrary API rằng khởi trị đầu thành công. Nó trả về zero thì DLL sẽ remove khỏi process. Vì vậy sau cùng của dll ta cần set eax:
mov eax, 1
leave
5/Viết file .def:
Để export hàm của bạn, bạn cần write một file '.def'
Các file definition files (.def) này dường như rất giống C++. Tôi ko biết nhiều về chúng nhưng tôi biết bạn có thể viết như sau cho việc export hàm của bạn:
EXPORTS
myFunction
File .def nên đặt cùng tên với file asm của dll
6/Các file inc được kèm vào như dll.inc:
Dùng để chứa các hàm import, ví dụ
extrn ActivateActCtx:proc
extrn AddAtomA:proc
extrn AddAtomW:proc
còn struct.inc, để chứa các cấu trúc phục vụ cho coding dll
7/Biên dịch:
Không có resource, ta tạo file bat để biên dịch:
;------------------------------------------------------------------------------
@echo off
if exist %1.obj del %1.obj
if exist %1.exe del %1.exe
: -----------------------------------------
: assemble *.asm into an OBJ file
: -----------------------------------------
C:\tasm32\bin\TASM32.EXE /ml /z /m9 /q %1.asm
if errorlevel 1 goto errasm
: -----------------------
: link the main OBJ file
: -----------------------
c:\tasm32\bin\tlink32 /Tpd /aa /c /x %1.obj,,,c:\tasm32\importlib\import32.lib,%1.def
if errorlevel 1 goto errlink
;----------------------------
;pewrite
;---------------------------
c:\tasm32\tasm32\pewrite %1.exe
if errorlevel 1 goto errpewrite
goto TheEnd
:errlink
: ----------------------------------------------------
: display message if there is an error during linking
: ----------------------------------------------------
echo.
echo There has been an error while linking this project.
echo.
goto TheEnd
:errasm
: -----------------------------------------------------
: display message if there is an error during assembly
: -----------------------------------------------------
echo.
echo There has been an error while assembling this project.
echo.
goto TheEnd
: -----------------------------------------------------
: display message if there is an error during pewrite
: -----------------------------------------------------
:errpewrite
echo.
echo There has been an error while pewrite this project.
echo.
goto TheEnd
:TheEnd
:if exist %1.obj del %1.obj
pause
;----------------------------------------------------------
Ví dụ cụ thể:
a/dll.asm như sau:
1: .586p
2: .model flat, stdcall
3: locals
4: jumps
5:
6: include dll.inc
7:
8: .data
9:
10: msg_title DB "Dll title",0
11: msg_message DB "Hello World! dll loader",0
12: msg_message_func DB "dll func loader",0
13:
14:
15:
16: .code
17: ;dllmain, entrypoint dll
18: start proc
19: arg imagebase
20: arg reason
21: arg reserved
22:
23: pushad
24: cmp reason, 1
25: jne __e_dllinit
26:
27: ;(code here)
28: push 0
29: push offset msg_title
30: push offset msg_message
31: push 0
32: call MessageBoxA
33:
34: __e_dllinit: popad
35: mov eax, 1
36: leave
37: retn 0ch
38: endp
39: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
40: public myFunction
41:
42: myFunction PROC
43: push 0
44: push offset msg_title
45: push offset msg_message_func
46: push 0
47: call MessageBoxA
48: ret
49: myFunction ENDP
50:
51: end start
b/dll.inc như sau:
extrn ExitProcess:proc
extrn MessageBoxA:proc
c/dll.def như sau:
EXPORTS
myFunction
d/Loader gọi hàm trong dll như sau:
Phần loader này ko kiểm tra giá trị trả về của các APIs:
1: .586p
2: .model flat
3: locals
4: jumps
5:
6: extrn ExitProcess:proc
7: extrn MessageBoxA:proc
8: extrn LoadLibraryA:proc
9: extrn GetProcAddress:proc
10:
11:
12: o equ offset
13:
14: .data
15:
16: msg_title DB "MessageBox title",0
17: msg_message DB "Hello World!",0
18:
19: dllname db "dll.DLL",0
20: dllfunc db "myFunction",0
21:
22: hlib dd ?
23: fn_myFunction dd ?
24:
25: .code
26: start:
27:
28: push 0
29: push offset msg_title
30: push offset msg_message
31: push 0
32: call MessageBoxA
33:
34: push o dllname
35: call LoadLibraryA
36: mov hlib,eax
37:
38:
39: push o dllfunc
40: push hlib
41: call GetProcAddress
42: mov fn_myFunction,eax
43:
44: call fn_myFunction
45:
46: push 0
47: call ExitProcess
48:
49: end start