html tool

显示标签为“dll”的博文。显示所有博文
显示标签为“dll”的博文。显示所有博文

2020年6月29日星期一

rust dll



所有 Rust 示例,都将使用 cargo 和libc 箱子。 每个示例的Cargo.toml,都包含以下样板:

[dependencies]
libc = "*"

[lib]
crate-type = ["cdylib"]

crate-type = ["cdylib"]会创建一个动态链接的库。 可查看 Cargo 文档的动态或静态库,了解更多信息.


让我们开始一些更复杂的东西,接受字符串参数。在 Rust 中,字符串由一组u8切片组成,并保证是有效的 UTF-8,允许NUL字节,在字符串内部。在 C 中,字符串只是指向一个char的指针,用一个NUL字节作为终止 (带整数值0) 。需要做一些转换工作,才能在处理好这两种表达。

extern crate libc;

use libc::{c_char, uint32_t};
use std::ffi::CStr;
use std::str;

#[no_mangle]
pub extern fn how_many_characters(s: *const c_char) -> uint32_t {
    let c_str = unsafe {
        assert!(!s.is_null());

        CStr::from_ptr(s)
    };

    let r_str = c_str.to_str().unwrap();
    r_str.chars().count() as uint32_t
}

获取一个 Rust 字符串切片 (&str) 需要几个步骤:

  1. 我们必须确保 C 指针不是NULL,因为 Rust 引用不能NULL。(会在 C 语言调用该函数,对应的,在 C 中,字符串只是指向一个char的指针,所以,该 Rust 函数的字符串参数,会迎来一个 C 指针。)

  2. 使用std::ffi::CStr包装指针。CStr将根据终止的NUL,计算字符串的长度。这需要一个unsafe区块,因为我们将解引用一个原始指针,Rust 编译器无法验证该指针,满足所有安全保证,因此程序员必须这样做。(unsafe的作用,不是说有多么特殊,只是为了让人们更快,且更好地注意到,存在安全隐患的代码。)

  3. 确保 C 字符串是有效的 UTF-8 ,并将其转换为 Rust 字符串切片。

  4. 使用字符串切片。

Python

#!/usr/bin/env python3
# coding: utf-8

import sys, ctypes
from ctypes import c_uint32, c_char_p

prefix = {'win32': ''}.get(sys.platform, 'lib')
extension = {'darwin': '.dylib', 'win32': '.dll'}.get(sys.platform, '.so')
lib = ctypes.cdll.LoadLibrary(prefix + "string_arguments" + extension)

lib.how_many_characters.argtypes = (c_char_p,)
lib.how_many_characters.restype = c_uint32

print(lib.how_many_characters("göes to élevên".encode('utf-8')))

Python 字符串,必须编码为 UTF-8,才能通过 FFI 边界.




2018年11月19日星期一

对比dll 动态链接库的加载顺序 在windows/linux 系统上的不同


linux动态链接库的加载顺序:


linux动态链接库的加载顺序:
它有5个地方会查找,
1. 编译时指定的run path 
[popexizhi:
    查看run path方式 readelf -d test 可以看到(RPATH) Library rpath: [pos1] 
   PS: readelf 是linux下的elf文件的读取工具很好用的,
            详细参见    https://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/readelf.html
]
2. LD_LIBRARY_PATH 指定的地方
[ popexizhi: 需要用LD_LIBRARY_PATH 说明。此例为: export LD_LIBRARY_PATH=./pos2
]
3. ldconfig 指定的地方
[popexizhi: 需要在/etc/ld.so.conf 中指明,此例为:/home/hjj/MyTest/temp/pos3
         然后ldconfig 生成缓存使设置生效 
]
4. /lib
5. /usr/lib

参考:https://blog.csdn.net/hejinjing_tom_com/article/details/52454478
[popexizhi:这里写的很全,作者推荐使用 strace和 编译dll 五个位置依次测试的方法都很好用 ,mark一下]


Windows动态链接库的加载顺序:


参考: https://payloads.online/archivers/2018-06-09/1


应用程序寻找DLL的过程
0.注册表\KnownDlls 
[popexizhi:
  系统启动时,smss.exe 会根据设置项创建一个 \KnownDlls 目录,其中存放了各个KnownDlls的Section对象。当系统需求加载dll时,优先从\KnownDlls对象目录中查找,如果有直接使用NtMapViewOfSection将其映射到内存。如果没有继续搜索。P462 《加密与解密-第4版》
]
1.程序所在目录
[popexizhi:
此位置是正在加载dll的进程的可执行文件的目录,这里是dll劫持的最后位置
]
2.系统目录即 SYSTEM32 目录
3.16位系统目录即 SYSTEM 目录
4.Windows目录
5.加载 DLL 时所在的当前目录
[popexizhi: 这个位置与1的区别,pope推断是,这里是正在加载DLL的进程的当前目录,此位置执行使用的目录,例如1为此c:\test\a.exe, 而在d:\ 下调用,步骤1是c:\test\, 步骤3是 d:\ ]
6.PATH环境变量中列出的目录

到这里还没有系统就提示找不到dll了。