问题描述
我在汇编程序中有一个小程序,它使用 dlopen
加载 .so 文件,然后尝试使用 dlsym
加载函数指针。调用 dlopen
似乎没问题,但是当我调用 dlsym
时它崩溃了。
SECTION .text
;default rel
EXTERN dlopen ; loads a dynamic library
EXTERN dlsym ; retrieves the address for a symbol in the dynamic library
; inputs:
; rdi: rdi the pointer to print
printHex:
sub rsp,19 ; allocate space for the string 0x0123456789ABCDEF\n
mov BYTE [rsp + 0],'0'
mov BYTE [rsp + 1],'x'
xor rcx,rcx ; int loop variable to 0
.LOOP1:
lea rsi,[rsp + rcx] ; rsi will we the offset where we will store the next hex charcter
mov rax,rdi
and rax,0xf
sar rdi,4 ; shift right 4 bits (divide by 16)
lea rdx,[hexLookUp + rax]
mov bl,[rdx]
mov BYTE [rsi +18],bl
dec rcx ; rcx--
cmp rcx,-16 ; while rcx > -16
jne .LOOP1
mov BYTE [rsp + 18],10
; print
mov rax,1 ; syscall: write
mov rdi,1 ; stdout
mov rsi,rsp
mov rdx,19
syscall
; release stack memory
add rsp,19
ret
global _start ; "global" means that the symbol can be accessed in other modules. In order to refer to a global symbol from another module,you must use the "extern" keyboard
_start:
; load the library
mov rdi,str_libX11so
mov rsi,2; RTLD_Now=2
call dlopen wrt ..plt
; plt stands for Procedure Linkage Table:
; used to call external library functions whose address is not kNow at link time,; so it must be resolved by the dynamic linker at run time
; more info: https://reverseengineering.stackexchange.com/questions/1992/what-is-plt-got
mov [ptr_libX11so],rax ; the prevIoUs function call returned the value in rax
mov rdi,rax
call printHex
; load the function
mov rdi,[str_libX11so]
mov rsi,fstr_XOpendisplay
call dlsym wrt ..plt
mov [fptr_XOpendisplay],rax
mov rdi,rax
call printHex
mov rax,60 ; syscal: exit
mov rdi,0 ; return code
syscall
hexLookUp: db "0123456789ABCDEF"
str_libX11so: db "libX11.so",0
; X11 function names
fstr_XOpendisplay: db "XOpendisplay",0
SECTION .data
ptr_libX11so: dq 0 ; ptr to the X11 library
; X11 function ptrs
fptr_XOpendisplay: dq 0
我尝试用 C 编写相同的程序,它似乎有效。所以我一定是做错了什么。
extern void* dlopen(const char* name,int);
extern void* dlsym(void* restrict handle,const char* restrict name);
int main()
{
void* libX11so = dlopen("libX11.so",2);
void (*XOpendisplay)() = dlsym(libX11so,"XOpendisplay");
}
我尝试反汇编 C 版本并进行比较,但仍然无法弄清楚问题所在。
我注意到一个有趣的事情是 dlopen
返回的指针(每次执行都不同),在 asm 版本中与 C 版本相比非常小(例如 0x0000000001A932D
vs {{ 1}})。但这可能是因为我使用 0x5555555592d0
标志进行链接:
-no-pie
解决方法
我刚刚注意到我的错误:
; load the function
mov rdi,[str_libX11so]
应该是:
; load the function
mov rdi,[ptr_libX11so]