Tải bản đầy đủ (.pdf) (8 trang)

Tài liệu Xây dựng thư viện liên kết động trong MASM doc

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (253.06 KB, 8 trang )






Trang 1
Xây dựng thư viện liên kết động trong MASM
Translated and Written by NhatPhuongLe
www.reaonline.net













Tutorial 17
Building a DLL in MASM32

















Reverse Engineering Association
Iczelions Win32 Assembly Tutorials 
For more updated info, please check





Xây dựng thư viện liên kết động trong MASM
Translated and Written by NhatPhuongLe
www.reaonline.net
1. Lý thuyết

Nếu bạn lập trình đủ lâu, thì bạn nhận thấy rằng các chương trình mà trước đây bạn
viết thường có những đoạn code giống nhau, nó thường là các thủ hàm (routines). Nó giúp
bạn tiết kiệm thời gian tránh phải viết lại mỗi khi bắt đầu viết một chương trình mới. Trở lại
thời lập trình trên nền DOS, những hàm thường xuyên được gọi sử dụng, sẽ được lưu trữ
trong tập tin đối tượng (.OBJ, .LIB, .
RES). Khi bạn muốn sử dụng các hàm này, bạn chỉ liên
kết tới tập tin đối tượng này, sau đó trình liên kết sẽ extract các hàm này và nhúng nội dung
của hàm vào tập tin EXE. Tiến trình này được gọi là liên kết tĩnh. Các thư viện lúc biên dịch

trong ngôn ngữ lập trình C là ví dụ dễ thấy nhất.
Liên kết tĩnh không hiệu quả bởi vì đoạn mã để thực thi một hàm thường phải nhúng
nhiều lần vào các tập tin .EX
E khác nhau. Không gian đĩa cứng của bạn sẽ tốn nhiều bộ
nhớ để lưu trữ các bản sao của hàm. Tuy nhiên, phương pháp này có thể chấp nhận được
bởi vì thường chỉ có một chương trình được gọi thực thi trên bộ nhớ. Tuy nhiên, dưới nền
tảng Windows thì việc tiết kiệm bộ nhớ được quan tâm hơn bởi vì có thể có nhiều chương
trình chạy cùng lúc. Lúc này, bộ nhớ được chia
nhau sử dụng bởi các chương trình, và nếu
như chương trình bạn càng lớn thì nó sẽ “ngốn” bộ nhớ càng nhiều. Windows đã đưa ra
hướng giải quyết cho vấn đề này là thư viện liên kết động. Windows sẽ không nạp các bản
sao của một DLL lên bộ nhớ vì thế thậm chí có nhiều thể hiện của chương trình đang chạy
cùng 1 lúc, cũng chỉ có duy nhất một bản sao của DLL
mà chương trình đang sử dụng được
nạp lên bộ nhớ.
Tôi giải thích rõ hơn cho bạn hiểu. Thực ra, tất cả các tiến trình đều sử dụng chung
một DLL, mà DLL này chính là bản sao của chính nó. Điều này thì tương tự như là có nhiều
bản sao của DLL trong bộ nhớ. Nhưng trong thực tế, Windows sẽ “thực hiện” điều này bằng
cách phân trang bộ nhớ và tất cả các tiến trình sẽ chia sẻ m
ã nguồn của cùng 1 DLL. Vì thế
trong bộ nhớ vật lý, chỉ có duy nhất một bản sao của mã nguồn DLL. Tuy nhiên, mỗi tiến
trình sẽ có một section dữ liệu của DLL cho riêng nó.
Chương trình liên kết với DLL lúc thực thi không giống như kiểu liên kết tĩnh cũ. Đó
là lý do tại sao nó được gọi là thư viện liên kết động. Bạn cũng có thể giải phóng DLL tại
thời điểm biên dịch khi bạn không sử dụng nó
nữa. Nếu như chỉ có một chương trình của
bạn sử dụng DLL, nó sẽ được giải phóng ra khỏi bộ nhớ ngay lập tức. Nhưng nếu như DLL
này vẫn được sử dụng bởi các chương trình khác, thì DLL vẫn còn nằm trên bộ nhớ cho
đến khi chương trình cuối cùng sử dụng nó xong và yêu cầu giải phóng nó ra khỏi bộ nhớ.
Tuy nhiên, trình linker sẽ có một nhiệm vụ khó hơn phải làm đó là fi

x lại địa chỉ cho tập tin
EXE. Bởi vì khi nó không thể “extract” các hàm và nhúng nội dung của hàm vào trong tập tin
EXE, bằng cách này hay cách khác nó phải lưu trữ đầy đủ thông tin về DLL và các hàm
trong tập tin EXE để nó có thể định vị và nạp lại một chính xác DLL tại thời điểm biên dịch.
Quá trình này được gọi là base relocation. Đây là nơi mà thư viện nhập được import. Một
thư viện nhập chứa thông tin về DLL. Trình linker có thể extract thông tin khi nó cần từ thư
viện nhập vào tập t
in EXE. Khi Windows Loader nạp chương trình vào bộ nhớ, nó sẽ tìm
xem chương trình có liên kết với DLL hay không, nó sẽ tìm DLL đó và ánh xạ nó vào trong
không gian địa chỉ của tiến trình và tiến hành fix địa chỉ của các hàm call gọi tới các hàm
trong DLL.
Bạn cũng có thể lựa chọn cách nạp DLL vào bộ nhớ bằng cách riêng của bạn không cần
nhờ vào Windows Loader. Phương pháp này có những thuận lợi và khó khăn sau:

Trang 2

Reverse Engineering Association




Xây dựng thư viện liên kết động trong MASM
Translated and Written by NhatPhuongLe
www.reaonline.net

Nó không cần phải import bất kỳ thư viện nhập nào vì thế bạn có thể nạp và sử dụng
DLL thậm chí nó đi kèm với thư viện nhập. Tuy nhiên, bạn vẫn phải biết thông tin về
các hàm bên trong DLL, có báo nhiêu tham số được truyền vào hàm hay đại loại thế.
 Khi bạn “nhờ” loader nạp DLL cho chương trình của bạn, nếu như loader không tìm
thấy DLL nó sẽ thông báo “A required .DLL file, xxx.dll is missing”, và chương

trình của bạn không thể run thậm chí nếu như DLL không thật sự cần t
hiết cho xử lý
trong chương trình chính đang gọi. Nhưng khi bạn nạp DLL theo cách của bạn thì khi
DLL không được tìm thấy và nó không cần thiết cho xử lýu của chương trình, thì
chương trình chỉ thông báo cho bạn biết và chương trình vẫn run tốt.
 Nếu bạn sử dụng LoadLibrary, bạn phải gọi hàm GetProcAddress cho mỗi hàm mà
bạn muốn gọi. GetProAddress sẽ cho bạn địa chỉ entrypoint của một hàm trong DLL
có liên quan. Vì thế mã nguồn của bạn có thể dài
hơn một tí và chậm hơn một chút
khi thực thi. Tuy nhiên, nó không đáng kể so với thuận lợi, bạn có thể nạp DLL
không cần nhờ loader.
Thấy được ưu và khuyết điểm của việc gọi hàm LoadLibrary, chúng ta sẽ đi vào chi tiết
làm thế nào để tạo một DLL.
Đây là cấu trúc của một DLL chuẩn:
DLLSkeleton.asm
.386
.model flat,stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib

DllEntry proc hInstance:HINSTANCE,reason:DWORD, reserved1:DWORD
...
mov eax,TRUE
ret
DllEntry Endp


Function proc
...
ret
Function endp

End DllEntry
DLLSkeleton.DEF
LIBRARY DLLSkelton
EXPORTS Function

Trang 3

Reverse Engineering Association




Xây dựng thư viện liên kết động trong MASM
Translated and Written by NhatPhuongLe
www.reaonline.net
Trên đây là cấu trúc chung của một chương trình DLL. Mỗi DLL phải có điểm vào
(entrypoint) của hàm. Hàm DllEntry trong DLL sẽ được gọi khi thư viện được Windows
nạp vào bộ nhớ và khi Windows yêu cầu chấm dứt.
DllEntry proc hInstance:HINSTANCE,reason:DWORD, reserved1:DWORD
...
mov eax,TRUE
ret
DllEntry Endp
Bạn có thể đặt tên entrypoint của DLL tùy ý, miễn sao là tên này giống với tên sau

nhãn END

End DllEntry
Hàm này nhận vào 3 tham số, trong đó có 2 tham số quan trọng là hInstance và
reversed1:
 Tham số đầu tiên mà hàm này sử dụng là mã thể hiện của thư viện hay còn gọi
là instance handle (tìm hiểu sâu vào kiến trúc Windows 32-bits, bạn sẽ thấy
instacne handle chính là địa chỉ vùng nhớ đầu tiên nơi thư viện DLL được nạp
vào). Nếu thư viện của bạn sử dụng đến những tài nguyên yêu cầu cung cấp mã
thể hiện của chương trình gọi (như Dialogbox chẳng hạn) thì bạn cần phải lưu
biến hInstan
ce này như một biến toàn cục.
 Tham số thứ 2 là reason, tham số này có thể mang 4 giá trị cho biết nguyên do
và tại sao Dll được Windows nạp vào bộ nhớ. Trong phần tiếp theo đây, bạn hãy
hình dung ngữ cảnh trong đó một chương trình ứng dụng được cho kích hoạt và
chạy nhiều lần song song với nhau. Mỗi lần chương trình được gọi, Windows
xem đó như là một tiến trình (process). Mỗi tiến trình nằm trong một vùng không
gian địa chỉ ảo độc lập với nhau.
Giá trị tham
số reason Ý nghĩa
DLL_PROCESS_ATTACH
 Hàm DllEntry với tham số
DLL_PROCESS_ATTACH được gọi khi process
tiến hành load DLL
 Thư viện DLL đang được Windows ánh xạ vào
vùng nhớ của tiến trình (thực hiện lời gọi DLL)
 Đây là thời điểm để DLL khởi tạo các biến, cấp
phát vùng nhớ hay những thao tác cần thiết
khác trước khi cho phép tiến trình gọi đến các
hàm của thư viện

DLL_PROCESS_DETACH

 Thư viện DLL được giải phóng khỏi vùng nhớ
của tiến trình do 1 trong 3 nguyên nhân: nạp
DLL không thành công, tiến trình kết thúc, hay
tiến trình gọi hàm FreeLibrary.
 Đây là thời điểm để giải phóng các biến hay tài
nguyên mà DLL đã cấp phát


Trang 4

Reverse Engineering Association




Xây dựng thư viện liên kết động trong MASM
Translated and Written by NhatPhuongLe
www.reaonline.net

DLL_THREAD_ATTACH
 Khi tiến trình tạo mới một tiểu trình (Thread),
Windows gọi hàm DllEntry của tất cả các thư
viện DLL đang được sử dụng với tiến trình đó.
 Đây là thời điểm để khởi tạo các biến dùng cho
tiểu trình
 Lưu ý rằng tình huống này chỉ xảy ra khi tiểu
trình được tạo sau khi thư viện DLL đã load vào
tiến trình, nghĩa là nếu DLL được load bằng hàn

LoadLibrary thì tất cả các t
iểu trình hiện có
(trong tiến trình) sẽ không gọi hàm DllEntry với
tham số này.
DLL_THREAD_DETACH
 Khi 1 tiểu trình kết thúc, Windows gọi hàm
DllEntry của tất cả các thư viện DLL đang được
sử dụng với tiểu trình này.
 Đây là thời điểm để giải phóng các biến dùng
cho tiểu trình
 Tham số cuối cùng truyền cho hàm DllEntry là reversed1 được hệ thống dành
cho mục đích riêng.
Bạn trả về giá
trị TRUE cho thanh ghi EAX, nếu như bạn muốn DLL chạy. Ngược lại,
nếu EAX chứa giá trị FALSE thì DLL sẽ không được nạp. Ví dụ, nếu code khởi tạo chỉ
định một số vùng nhớ và nó không thể làm điều đó thành công, thì hàm DllEntry sẽ trả
về giá trị FALSE để chỉ ra rằng DLL không thể chạy được.
Bạn có thể đặt các hàm
của bạn trong DLL trước hoặc sau entrypoint đều được.
Nhưng nếu bạn muốn nó có thể được gọi từ chương trình khác bạn phải đặt các hàm
trong export list chính là danh sách các hàm được export ra bên ngoài cho các DLL hoặc
chương trình khác sử dụng trong file định nghĩa (.DEF)
LIBRARY DLLSkelton
EXPORTS Function
Thông thường, bạn phải có dòng đầu tiên. Phát biểu LIBRARY sẽ định nghĩa tên
module bên trong của DLL. Bạn nên để nó phù hợp với tên file của DLL (trong ví dụ này
là DLLSkeleton). Phát biểu EXPORTS sẽ nói cho trình linker biết những hàm nào trong
DLL được export, đó là những hàm có thể được gọi bởi các chương trình khác. Trong ví
dụ này, chúng ta muốn các modules khác có thể gọi hàm Function, vì thế ta đặt tên của
hàm này (Function) phía sau phát biểu EXPORT.

 Nếu bạn không viết code trên một IDE dành riêng cho asm, thì bạn có thể viết một tập
tin .BAT để biên
dịch và liên kết các tập tin đối tượng. Tuy nhiên, có một sự thay đổi
trong việc viết lệnh trong file .BAT như sau:
Thông thường, bạn muốn trình linker sau khi liên kết các tập tin đối tượng thành tập tin
.EXE thì bạn viết lệnh như sau:
\masm32\bin\Link /SUBSYSTEM:WINDOWS /OUT:xxx.exe xxx.obj

Trang 5

Reverse Engineering Association

×