从汇编程序调用时 dlsym 崩溃
dlsym crash when called from assembler
我在汇编程序中有一个小程序,它使用 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 0x5555555592d0
)。但也许那可能是因为我使用 -no-pie
标志进行链接:
nasm -f elf64 -g -F dwarf minimal.asm && gcc -nostartfiles -no-pie minimal.o -ldl -o minimal && ./minimal
我刚刚注意到我的错误:
; load the function
mov rdi, [str_libX11so]
应该是:
; load the function
mov rdi, [ptr_libX11so]
我在汇编程序中有一个小程序,它使用 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 0x5555555592d0
)。但也许那可能是因为我使用 -no-pie
标志进行链接:
nasm -f elf64 -g -F dwarf minimal.asm && gcc -nostartfiles -no-pie minimal.o -ldl -o minimal && ./minimal
我刚刚注意到我的错误:
; load the function
mov rdi, [str_libX11so]
应该是:
; load the function
mov rdi, [ptr_libX11so]