mirror of
https://github.com/b1tg/rust-windows-shellcode
synced 2026-06-08 13:14:11 +00:00
Ready to publish
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
[build]
|
||||
target = "x86_64-pc-windows-msvc"
|
||||
# target = "i686-pc-windows-msvc"
|
||||
|
||||
rustflags = [
|
||||
# Pre Link Args
|
||||
#"-Z", "pre-link-arg=/NOLOGO",
|
||||
#"-Z", "pre-link-arg=/NXCOMPAT",
|
||||
"-Z", "pre-link-arg=/NODEFAULTLIB",
|
||||
#"-Z", "pre-link-arg=/DYNAMICBASE",
|
||||
#"-Z", "pre-link-arg=/MANIFEST:NO",
|
||||
"--emit", "asm",
|
||||
# Post Link Args
|
||||
"-C", "link-arg=/ENTRY:main",
|
||||
#"-C", "link-arg=/OPT:REF,ICF",
|
||||
"-C", "link-arg=/MERGE:.edata=.rdata",
|
||||
"-C", "link-arg=/MERGE:.rustc=.data",
|
||||
"-C", "link-arg=/MERGE:.rdata=.text",
|
||||
"-C", "link-arg=/MERGE:.pdata=.text",
|
||||
#"-C", "link-arg=/INTEGRITYCHECK"
|
||||
"-C", "link-arg=/DEBUG:NONE",
|
||||
"-C", "link-arg=/EMITPOGOPHASEINFO",
|
||||
"-C", "target-feature=-mmx,-sse,+soft-float"
|
||||
|
||||
|
||||
|
||||
]
|
||||
Generated
+78
@@ -0,0 +1,78 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f"
|
||||
dependencies = [
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shellcode"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"num",
|
||||
"num-traits",
|
||||
]
|
||||
@@ -0,0 +1,30 @@
|
||||
[package]
|
||||
name = "shellcode"
|
||||
version = "0.1.0"
|
||||
authors = ["b1tg <b1tg@users.noreply.github.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
# these two cut code size by 2/3
|
||||
opt-level = "z"
|
||||
lto = true
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
# these two cut code size by 2/3
|
||||
opt-level = "z"
|
||||
lto = true
|
||||
|
||||
[dependencies.num]
|
||||
version = "0.3"
|
||||
default-features = false
|
||||
|
||||
[dependencies.num-traits]
|
||||
version = "0.2"
|
||||
default-features = false
|
||||
@@ -0,0 +1,202 @@
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
pub enum c_void {}
|
||||
pub type BOOLEAN = u8;
|
||||
pub type HANDLE = *mut c_void;
|
||||
pub type PVOID = *mut c_void;
|
||||
pub type ULONG = u32;
|
||||
pub type LPSTR = *mut i8;
|
||||
#[repr(C)]
|
||||
pub struct PEB {
|
||||
pub InheritedAddressSpace: BOOLEAN,
|
||||
pub ReadImageFileExecOptions: BOOLEAN,
|
||||
pub BeingDebugged: BOOLEAN,
|
||||
pub BitField: BOOLEAN,
|
||||
pub Mutant: HANDLE,
|
||||
pub ImageBaseAddress: PVOID,
|
||||
pub Ldr: *mut PEB_LDR_DATA,
|
||||
pub ProcessParameters: *mut RTL_USER_PROCESS_PARAMETERS,
|
||||
}
|
||||
pub type LPCSTR = *const i8;
|
||||
#[repr(C)]
|
||||
pub struct PEB_LDR_DATA {
|
||||
pub Length: ULONG,
|
||||
pub Initialized: BOOLEAN,
|
||||
pub SsHandle: HANDLE,
|
||||
pub InLoadOrderModuleList: LIST_ENTRY,
|
||||
// ...
|
||||
}
|
||||
|
||||
pub type PLDR_DATA_TABLE_ENTRY = *const LDR_DATA_TABLE_ENTRY;
|
||||
#[repr(C)]
|
||||
pub struct LDR_DATA_TABLE_ENTRY {
|
||||
pub InLoadOrderModuleList: LIST_ENTRY,
|
||||
pub InMemoryOrderModuleList: LIST_ENTRY,
|
||||
pub InInitializationOrderModuleList: LIST_ENTRY,
|
||||
pub BaseAddress: PVOID,
|
||||
pub EntryPoint: PVOID,
|
||||
pub SizeOfImage: ULONG,
|
||||
pub FullDllName: UNICODE_STRING,
|
||||
pub BaseDllName: UNICODE_STRING,
|
||||
// ...
|
||||
}
|
||||
|
||||
pub type USHORT = u16;
|
||||
pub type PWCH = *mut u16;
|
||||
pub type DWORD = u32;
|
||||
pub type WORD = u16;
|
||||
pub type ULONGLONG = u64;
|
||||
pub type BYTE = u8;
|
||||
pub type LONG = u32;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct UNICODE_STRING {
|
||||
pub Length: USHORT,
|
||||
pub MaximumLength: USHORT,
|
||||
pub Buffer: PWCH,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct LIST_ENTRY {
|
||||
pub Flink: *mut LIST_ENTRY,
|
||||
pub Blink: *mut LIST_ENTRY,
|
||||
}
|
||||
#[repr(C)]
|
||||
pub struct RTL_USER_PROCESS_PARAMETERS {
|
||||
pub MaximumLength: ULONG,
|
||||
pub Length: ULONG,
|
||||
pub Flags: ULONG,
|
||||
pub DebugFlags: ULONG,
|
||||
pub ConsoleHandle: HANDLE,
|
||||
pub ConsoleFlags: ULONG,
|
||||
pub StandardInput: HANDLE,
|
||||
pub StandardOutput: HANDLE,
|
||||
pub StandardError: HANDLE,
|
||||
}
|
||||
|
||||
type PULONG = *mut ULONG;
|
||||
#[repr(C)]
|
||||
pub struct IO_STATUS_BLOCK {
|
||||
_1: IO_STATUS_BLOCK_u,
|
||||
_2: PULONG,
|
||||
}
|
||||
/// A specialized `Result` type for NT operations.
|
||||
pub type Result<T> = ::core::result::Result<T, Status>;
|
||||
|
||||
/// NT Status code.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Status {
|
||||
success = 0,
|
||||
unsuccessful = 0xC0000001,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub union IO_STATUS_BLOCK_u {
|
||||
_1: NTSTATUS,
|
||||
_2: PVOID,
|
||||
}
|
||||
pub type NTSTATUS = Status;
|
||||
type HMODULE = HINSTANCE;
|
||||
type HINSTANCE = *mut HINSTANCE__;
|
||||
pub enum HINSTANCE__ {}
|
||||
// ====
|
||||
#[repr(C)]
|
||||
pub struct IMAGE_DATA_DIRECTORY {
|
||||
pub VirtualAddress: DWORD,
|
||||
pub Size: DWORD,
|
||||
}
|
||||
#[repr(C)]
|
||||
pub struct IMAGE_DOS_HEADER {
|
||||
pub e_magic: WORD,
|
||||
pub e_cblp: WORD,
|
||||
pub e_cp: WORD,
|
||||
pub e_crlc: WORD,
|
||||
pub e_cparhdr: WORD,
|
||||
pub e_minalloc: WORD,
|
||||
pub e_maxalloc: WORD,
|
||||
pub e_ss: WORD,
|
||||
pub e_sp: WORD,
|
||||
pub e_csum: WORD,
|
||||
pub e_ip: WORD,
|
||||
pub e_cs: WORD,
|
||||
pub e_lfarlc: WORD,
|
||||
pub e_ovno: WORD,
|
||||
pub e_res: [WORD; 4],
|
||||
pub e_oemid: WORD,
|
||||
pub e_oeminfo: WORD,
|
||||
pub e_res2: [WORD; 10],
|
||||
pub e_lfanew: LONG,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct IMAGE_EXPORT_DIRECTORY {
|
||||
pub Characteristics: DWORD,
|
||||
pub TimeDateStamp: DWORD,
|
||||
pub MajorVersion: WORD,
|
||||
pub MinorVersion: WORD,
|
||||
pub Name: DWORD,
|
||||
pub Base: DWORD,
|
||||
pub NumberOfFunctions: DWORD,
|
||||
pub NumberOfNames: DWORD,
|
||||
pub AddressOfFunctions: DWORD,
|
||||
pub AddressOfNames: DWORD,
|
||||
pub AddressOfNameOrdinals: DWORD,
|
||||
}
|
||||
type ULONG_PTR = usize;
|
||||
|
||||
pub const IMAGE_DOS_SIGNATURE: WORD = 0x5A4D;
|
||||
|
||||
pub type IMAGE_NT_HEADERS = IMAGE_NT_HEADERS64;
|
||||
#[repr(C)]
|
||||
pub struct IMAGE_NT_HEADERS64 {
|
||||
pub Signature: DWORD,
|
||||
pub FileHeader: IMAGE_FILE_HEADER,
|
||||
pub OptionalHeader: IMAGE_OPTIONAL_HEADER64,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct IMAGE_FILE_HEADER {
|
||||
pub Machine: WORD,
|
||||
pub NumberOfSections: WORD,
|
||||
pub TimeDateStamp: DWORD,
|
||||
pub PointerToSymbolTable: DWORD,
|
||||
pub NumberOfSymbols: DWORD,
|
||||
pub SizeOfOptionalHeader: WORD,
|
||||
pub Characteristics: WORD,
|
||||
}
|
||||
#[repr(C)]
|
||||
pub struct IMAGE_OPTIONAL_HEADER64 {
|
||||
pub Magic: WORD,
|
||||
pub MajorLinkerVersion: BYTE,
|
||||
pub MinorLinkerVersion: BYTE,
|
||||
pub SizeOfCode: DWORD,
|
||||
pub SizeOfInitializedData: DWORD,
|
||||
pub SizeOfUninitializedData: DWORD,
|
||||
pub AddressOfEntryPoint: DWORD,
|
||||
pub BaseOfCode: DWORD,
|
||||
pub ImageBase: ULONGLONG,
|
||||
pub SectionAlignment: DWORD,
|
||||
pub FileAlignment: DWORD,
|
||||
pub MajorOperatingSystemVersion: WORD,
|
||||
pub MinorOperatingSystemVersion: WORD,
|
||||
pub MajorImageVersion: WORD,
|
||||
pub MinorImageVersion: WORD,
|
||||
pub MajorSubsystemVersion: WORD,
|
||||
pub MinorSubsystemVersion: WORD,
|
||||
pub Win32VersionValue: DWORD,
|
||||
pub SizeOfImage: DWORD,
|
||||
pub SizeOfHeaders: DWORD,
|
||||
pub CheckSum: DWORD,
|
||||
pub Subsystem: WORD,
|
||||
pub DllCharacteristics: WORD,
|
||||
pub SizeOfStackReserve: ULONGLONG,
|
||||
pub SizeOfStackCommit: ULONGLONG,
|
||||
pub SizeOfHeapReserve: ULONGLONG,
|
||||
pub SizeOfHeapCommit: ULONGLONG,
|
||||
pub LoaderFlags: DWORD,
|
||||
pub NumberOfRvaAndSizes: DWORD,
|
||||
pub DataDirectory: [IMAGE_DATA_DIRECTORY; 16],
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_upper_case_globals)]
|
||||
#![allow(overflowing_literals)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(asm)]
|
||||
#![feature(link_args)]
|
||||
use core::ptr::null_mut;
|
||||
mod binds;
|
||||
mod utils;
|
||||
use binds::*;
|
||||
use utils::*;
|
||||
#[panic_handler]
|
||||
fn panic(_: &core::panic::PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
||||
// const KERNEL32_DLL: &str = concat!("KERNEL32.DLL", "\0");
|
||||
const USER32_DLL: &str = concat!("user32.dll", "\0");
|
||||
const OutputDebugStringA_: &str = concat!("OutputDebugStringA", "\0");
|
||||
const LoadLibraryA_: &str = concat!("LoadLibraryA", "\0");
|
||||
const GetProcAddress_: &str = concat!("GetProcAddress", "\0");
|
||||
const MessageBoxA_: &str = concat!("MessageBoxA", "\0");
|
||||
|
||||
pub type LoadLibraryAFn = extern "system" fn(lpFileName: LPCSTR) -> PVOID;
|
||||
pub type GetProcAddressFn = extern "system" fn(hmodule: PVOID, name: LPCSTR) -> PVOID;
|
||||
pub type MessageBoxAFn = extern "system" fn(h: PVOID, text: LPCSTR, cation: LPCSTR, t: u32) -> u32;
|
||||
pub type OutputDebugStringAFn = extern "C" fn(*const i8);
|
||||
pub type DbgPrintFn = extern "C" fn(Format: *const u8, ...) -> NTSTATUS;
|
||||
#[no_mangle]
|
||||
pub extern "C" fn main() -> ! {
|
||||
unsafe {
|
||||
// clean argc and argv
|
||||
asm!("mov rcx, 0", "mov rdx, 0",);
|
||||
}
|
||||
let KERNEL32_STR: [u16; 13] = [75, 69, 82, 78, 69, 76, 51, 50, 46, 68, 76, 76, 0];
|
||||
let kernel32_ptr = get_module_by_name(KERNEL32_STR.as_ptr());
|
||||
let dbg_addr = get_func_by_name(kernel32_ptr, OutputDebugStringA_.as_ptr());
|
||||
let load_library_ptr = get_func_by_name(kernel32_ptr, LoadLibraryA_.as_ptr());
|
||||
let get_proc = get_func_by_name(kernel32_ptr, GetProcAddress_.as_ptr());
|
||||
let LoadLibraryA: LoadLibraryAFn = unsafe { core::mem::transmute(load_library_ptr) };
|
||||
|
||||
// make stack align
|
||||
unsafe { asm!("push rax") };
|
||||
let u32_dll = LoadLibraryA(USER32_DLL.as_ptr() as *const i8);
|
||||
let GetProcAddress: GetProcAddressFn = unsafe { core::mem::transmute(get_proc) };
|
||||
let message_box_ptr = GetProcAddress(u32_dll, MessageBoxA_.as_ptr() as *const i8);
|
||||
let MessageBoxA: MessageBoxAFn = unsafe { core::mem::transmute(message_box_ptr) };
|
||||
|
||||
let OutputDebugStringA: OutputDebugStringAFn = unsafe { core::mem::transmute(dbg_addr) };
|
||||
#[macro_export]
|
||||
macro_rules! debug_print {
|
||||
($msg:expr) => {
|
||||
OutputDebugStringA(concat!($msg, "\n\0").as_ptr() as _)
|
||||
};
|
||||
}
|
||||
debug_print!("We made it! see me in DebugView or Debugger");
|
||||
debug_print!("Let's popup a messagebox");
|
||||
MessageBoxA(
|
||||
null_mut(),
|
||||
"Windows Shellcode with Rust!\0".as_ptr() as *const i8,
|
||||
"rocks\0".as_ptr() as _,
|
||||
0x30,
|
||||
);
|
||||
loop {}
|
||||
}
|
||||
|
||||
fn get_module_by_name(module_name: *const u16) -> PVOID {
|
||||
let peb: *mut PEB;
|
||||
unsafe {
|
||||
asm!(
|
||||
"mov {}, gs:[0x60]",
|
||||
out(reg) peb,
|
||||
);
|
||||
let ldr = (*peb).Ldr;
|
||||
let list_entry = &((*ldr).InLoadOrderModuleList);
|
||||
let mut cur_module: *const LDR_DATA_TABLE_ENTRY = &list_entry as *const _ as *const _;
|
||||
loop {
|
||||
if cur_module.is_null() || (*cur_module).BaseAddress.is_null() {
|
||||
// TODO: when to break
|
||||
}
|
||||
let cur_name = (*cur_module).BaseDllName.Buffer;
|
||||
if !cur_name.is_null() {
|
||||
if compare_raw_str(module_name, cur_name) {
|
||||
return (*cur_module).BaseAddress;
|
||||
}
|
||||
}
|
||||
let flink = (*cur_module).InLoadOrderModuleList.Flink;
|
||||
cur_module = flink as *const LDR_DATA_TABLE_ENTRY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_func_by_name(module: PVOID, func_name: *const u8) -> PVOID {
|
||||
let idh: *const IMAGE_DOS_HEADER = module as *const _;
|
||||
unsafe {
|
||||
if (*idh).e_magic != IMAGE_DOS_SIGNATURE {
|
||||
return null_mut();
|
||||
}
|
||||
let e_lfanew = (*idh).e_lfanew;
|
||||
let nt_headers: *const IMAGE_NT_HEADERS =
|
||||
(module as *const u8).offset(e_lfanew as isize) as *const _;
|
||||
let op_header = &(*nt_headers).OptionalHeader;
|
||||
let virtual_addr = (&op_header.DataDirectory[0]).VirtualAddress;
|
||||
let export_dir: *const IMAGE_EXPORT_DIRECTORY =
|
||||
(module as *const u8).offset(virtual_addr as _) as _;
|
||||
let number_of_names = (*export_dir).NumberOfNames;
|
||||
let addr_of_funcs = (*export_dir).AddressOfFunctions;
|
||||
let addr_of_names = (*export_dir).AddressOfNames;
|
||||
let addr_of_ords = (*export_dir).AddressOfNameOrdinals;
|
||||
for i in 0..number_of_names {
|
||||
let name_rva_p: *const DWORD =
|
||||
(module as *const u8).offset((addr_of_names + i * 4) as isize) as *const _;
|
||||
let name_index_p: *const WORD =
|
||||
(module as *const u8).offset((addr_of_ords + i * 2) as isize) as *const _;
|
||||
let name_index = name_index_p.as_ref().unwrap();
|
||||
let mut off: u32 = (4 * name_index) as u32;
|
||||
off = off + addr_of_funcs;
|
||||
let func_rva: *const DWORD = (module as *const u8).offset(off as _) as *const _;
|
||||
|
||||
let name_rva = name_rva_p.as_ref().unwrap();
|
||||
let curr_name = (module as *const u8).offset(*name_rva as isize);
|
||||
|
||||
if *curr_name == 0 {
|
||||
continue;
|
||||
}
|
||||
if compare_raw_str(func_name, curr_name) {
|
||||
let res = (module as *const u8).offset(*func_rva as isize);
|
||||
return res as _;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null_mut();
|
||||
}
|
||||
// #[allow(unused_attributes)]
|
||||
// #[cfg(target_env = "msvc")]
|
||||
// #[link_args = "/GS- /MERGE:.rdata=.text /MERGE:.pdata=.text /NODEFAULTLIB /EMITPOGOPHASEINFO /DEBUG:NONE"]
|
||||
// extern "C" {}
|
||||
@@ -0,0 +1,88 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
|
||||
unsafe fn u16_ptr_len(ptr: *const u16) -> usize {
|
||||
let len = (0..).take_while(|&i| *ptr.offset(i) != 0).count();
|
||||
return len;
|
||||
}
|
||||
|
||||
fn compare_str_u16(s: &str, u: *const u16) -> bool {
|
||||
unsafe {
|
||||
let len = (0..).take_while(|&i| *u.offset(i) != 0).count();
|
||||
let slice = core::slice::from_raw_parts(u, len);
|
||||
let s_len = s.len();
|
||||
if len != s_len {
|
||||
return false;
|
||||
}
|
||||
let ss = s.as_bytes();
|
||||
for i in 0..len {
|
||||
if slice[i] != ss[i] as u16 {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: use alloc
|
||||
pub fn str_to_u16_ptr(s: &str, buf: &mut [u16]) {
|
||||
let s_len = s.len();
|
||||
let s_bytes = s.as_bytes();
|
||||
|
||||
// for i in 0..255 {
|
||||
|
||||
// }
|
||||
// let buf = vec![0u16;s_len+1];
|
||||
for i in 0..s_len {
|
||||
buf[i] = s_bytes[i] as _;
|
||||
}
|
||||
buf[s_len] = 0;
|
||||
// buf.as_ptr()
|
||||
}
|
||||
|
||||
use num_traits::Num;
|
||||
|
||||
pub fn compare_raw_str<T>(s: *const T, u: *const T) -> bool
|
||||
where
|
||||
T: Num,
|
||||
{
|
||||
unsafe {
|
||||
let u_len = (0..).take_while(|&i| !(*u.offset(i)).is_zero()).count();
|
||||
let u_slice = core::slice::from_raw_parts(u, u_len);
|
||||
|
||||
let s_len = (0..).take_while(|&i| !(*s.offset(i)).is_zero()).count();
|
||||
let s_slice = core::slice::from_raw_parts(s, s_len);
|
||||
|
||||
if s_len != u_len {
|
||||
return false;
|
||||
}
|
||||
for i in 0..s_len {
|
||||
if s_slice[i] != u_slice[i] {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
fn compare_str_u8(s: &str, u: *const u8) -> bool {
|
||||
unsafe {
|
||||
let len = (0..).take_while(|&i| *u.offset(i) != 0).count();
|
||||
let slice = core::slice::from_raw_parts(u, len);
|
||||
let s_len = s.len();
|
||||
if len != s_len {
|
||||
return false;
|
||||
}
|
||||
let ss = s.as_bytes();
|
||||
for i in 0..len {
|
||||
if slice[i] != ss[i] as u8 {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
fn str_to_i8(s: &str) -> *const i8 {
|
||||
s.as_bytes().as_ptr() as *const i8
|
||||
}
|
||||
Reference in New Issue
Block a user