Skip to content

Commit

Permalink
updated to DisZero 0.2.0
Browse files Browse the repository at this point in the history
Signed-off-by: armoha <kein0011@naver.com>
  • Loading branch information
armoha committed Jan 21, 2020
1 parent 4a928bb commit 7069576
Show file tree
Hide file tree
Showing 9 changed files with 1,282 additions and 299 deletions.
1,095 changes: 1,023 additions & 72 deletions Cargo.lock

Large diffs are not rendered by default.

24 changes: 12 additions & 12 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
[package]
name = "dis-zero"
version = "0.1.0"
version = "0.2.0"
authors = ["armoha <kein0011@naver.com>"]
license = "MIT/Apache-2.0"
edition = "2018"
build = "src/build.rs"

[dependencies]
winapi = { version = "^0.3", features = ["std", "everything"] }
libc = { version = "^0.2", features = ["use_std", "extra_traits"] }
getset = "^0.0"
failure = "^0.1"

[build-dependencies]
failure = "^0.1"

[target.'cfg(windows)'.build-dependencies]
winres = "0.1.9"
winapi = { version = "0.3", features = [ "tlhelp32", "handleapi" ] }
proclist = "0.9"
process-memory = "0.3.0"
reqwest = { version = "0.10", features = ["blocking", "json"] }

[package.metadata.winres]
OriginalFilename = "DisZero.exe"
LegalCopyright = "Copyright © 2019"
LegalCopyright = "Copyright © 2019-2020"
FileDescription = "DisZero"

# always use target build-dependencies for winres so that
# it won't get pulled for non-windows OSs (saves them resources)
[target.'cfg(target_os="windows")'.build-dependencies]
winres = "0.1.9"
winapi = { version = "0.3", features = [ "winnt" ] }
File renamed without changes.
23 changes: 23 additions & 0 deletions manifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows 8.0 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows 10.0 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
4 changes: 2 additions & 2 deletions scdata.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
"version": "1.23.2.6926",
"versionOffset32": "0x9FEA18",
"versionOffset64": "0xC532E8",
"dropTimerOffset32": "0x9FEA18",
"dropTimerOffset64": "0xC532E8"
"dropTimerOffset32": "0xC74044",
"dropTimerOffset64": "0xF0B31C"
}
40 changes: 27 additions & 13 deletions src/build.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,29 @@
use failure::Error;
#[cfg(target_os = "windows")]
use winres;
#[cfg(target_os = "windows")]
use winapi;

#[cfg(windows)]
fn add_icon() -> Result<(), Error> {
let mut res = winres::WindowsResource::new();
res.set_icon("resources/SCBank.ico");
res.compile()?;
Ok(())
}

#[cfg(windows)]
fn main() -> Result<(), Error> {
add_icon()?;
Ok(())
#[cfg(target_os = "windows")]
fn main() {
use std::io::Write;
// only build the resource for release builds
// as calling rc.exe might be slow
if std::env::var("PROFILE").unwrap() == "release" {
let mut res = winres::WindowsResource::new();
res.set_icon("DisZero.ico")
.set_language(
winapi::um::winnt::MAKELANGID(
winapi::um::winnt::LANG_KOREAN,
winapi::um::winnt::SUBLANG_KOREAN
)
)
.set_manifest_file("manifest.xml");
match res.compile() {
Err(e) => {
write!(std::io::stderr(), "{}", e).unwrap();
std::process::exit(1);
}
Ok(_) => {}
}
}
}
28 changes: 25 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,33 @@
mod mem_lib;
mod scr;
mod mem_lib;
use std::{thread, time};

fn main() {
let sc = &mut scr::StarCraft::default();
/*
let sc = mem_lib::ProcessInfo::get_pinfo_by_name("StarCraft.exe");
match sc {
Ok(s) => {
match s.read_address(0xC5_32E8, 11) {
Ok(v) => {
use std::str;
println!("{}", str::from_utf8(&v).unwrap());
}
Err(e) => {
println!("{}", e);
},
}
},
Err(_) => ()
};
*/
let sc = &mut scr::SCInfo::default();
println!("스타크래프트 최신 정보 가져오는 중...");
if let Err(e) = sc.update() {
println!("서버에서 스타크래프트 최신 정보를 가져오는데 실패했습니다. 인터넷 연결을 확인하세요\n: {:?}", e);
};
let wait = time::Duration::from_millis(80);
println!("스타크래프트 리마스터 {}버전만 지원합니다.", scr::STARCRAFT_VERSION);
println!("스타크래프트 리마스터 {}버전만 지원합니다.", sc.scdata.version);
loop {
sc.next();
sc.run();
Expand Down
179 changes: 46 additions & 133 deletions src/mem_lib.rs
Original file line number Diff line number Diff line change
@@ -1,59 +1,49 @@
use std::{ffi::OsString, mem, os::windows::ffi::OsStringExt};
// source: https://www.unknowncheats.me/forum/general-programming-and-reversing/330583-pure-rust-injectable-dll.html
use std::result::Result as StdResult;

use failure::{Error as FError, Fail};
use getset::Getters;
use winapi::um::{handleapi, memoryapi, processthreadsapi, tlhelp32, winnt};

#[derive(Getters)]
#[get = "pub"]
pub struct GameProcess {
handle: winnt::HANDLE,
pid: u32,
use proclist;
use std::{ffi::OsString, convert::TryInto, io, mem, os::windows::ffi::OsStringExt};
use process_memory::{Memory, DataMember, Pid, TryIntoProcessHandle, copy_address};
use winapi::um::{tlhelp32, handleapi};

pub struct ProcessInfo {
pub pid: Pid,
pub base_addr: usize,
}

#[derive(Getters, Default)]
#[get = "pub"]
pub struct Module {
base: u32,
}

pub type Result<T> = StdResult<T, FError>;

#[derive(Debug, Fail)]
pub enum ProcessErrorKind {
#[fail(display = "Couldn't read memory at {:#X}", _0)]
MemoryRead(u32),

#[fail(display = "CreateToolhelp32Snapshot returned INVALID_HANDLE_VALUE")]
pub enum Error {
NoProcessFound,
InvalidHandleValue,

#[fail(display = "Unknown process: {}", _0)]
UnknownProcess(String),

#[fail(display = "Unknown module: {}", _0)]
UnknownModule(String),

#[fail(display = "InvalidBytesWritten: {}", _0)]
InvalidBytesWritten(u32),
UnknownModule,
}

impl GameProcess {
pub fn current_process() -> Self {
Self::new(unsafe { processthreadsapi::GetCurrentProcess() })
impl Default for ProcessInfo {
fn default() -> ProcessInfo {
use std::process;

ProcessInfo {
pid: process::id(),
base_addr: 0,
}
}
}

pub fn new(handle: winnt::HANDLE) -> Self {
let pid = unsafe { processthreadsapi::GetProcessId(handle) };
GameProcess { handle, pid }
impl ProcessInfo {
pub fn get_pinfo_by_name(name: &str) -> Result<ProcessInfo, Error> {
for process_info in proclist::iterate_processes_info().filter_map(|r| r.ok()) {
if process_info.name == name {
let base_addr = ProcessInfo::get_modbaseaddr(process_info.pid, name)?;
return Ok(ProcessInfo {
pid: process_info.pid,
base_addr: base_addr,
});
}
}
Err(Error::NoProcessFound)
}

pub fn get_module(&self, module_name: &str) -> Result<Module> {
fn get_modbaseaddr(pid: Pid, module_name: &str) -> Result<usize, Error> {
let module =
unsafe { tlhelp32::CreateToolhelp32Snapshot(tlhelp32::TH32CS_SNAPMODULE, self.pid) };
unsafe { tlhelp32::CreateToolhelp32Snapshot(tlhelp32::TH32CS_SNAPMODULE, pid) };
if module == handleapi::INVALID_HANDLE_VALUE {
return Err(ProcessErrorKind::InvalidHandleValue.into());
return Err(Error::InvalidHandleValue);
}

let mut entry: tlhelp32::MODULEENTRY32W = unsafe { mem::zeroed() };
Expand All @@ -72,102 +62,25 @@ impl GameProcess {
if name.contains(module_name) {
unsafe { handleapi::CloseHandle(module) };

if cfg!(debug_assertions) {
println!(
"Base address of {}: 0x{:X} @ size of 0x{:X}",
module_name, entry.modBaseAddr as u32, entry.modBaseSize
);
}
/*println!(
"Base address of {}: 0x{:X} @ size of 0x{:X}",
module_name, entry.modBaseAddr as usize, entry.modBaseSize
);*/

return Ok(Module {
base: entry.modBaseAddr as _,
});
return Ok(entry.modBaseAddr as _);
}
}

Err(ProcessErrorKind::UnknownModule(module_name.into()).into())
Err(Error::UnknownModule)
}
}

pub fn get_proc_by_name(name: &str) -> Result<GameProcess> {
let mut process: tlhelp32::PROCESSENTRY32W = unsafe { mem::MaybeUninit::uninit().assume_init() };
process.dwSize = mem::size_of::<tlhelp32::PROCESSENTRY32W>() as u32;

//Make a Snapshot of all the current process.
let snapshot = unsafe { tlhelp32::CreateToolhelp32Snapshot(tlhelp32::TH32CS_SNAPPROCESS, 0) };

//Get the first process and store it in process variable.
if unsafe { tlhelp32::Process32FirstW(snapshot, &mut process) } != 0 {
//Take the next process if possible.
while unsafe { tlhelp32::Process32NextW(snapshot, &mut process) } != 0 {
let process_name = OsString::from_wide(&process.szExeFile);

match process_name.into_string() {
Ok(s) => {
if s.contains(name) {
return Ok(GameProcess {
handle: unsafe {
processthreadsapi::OpenProcess(
winnt::PROCESS_VM_READ
| winnt::PROCESS_VM_OPERATION
| winnt::PROCESS_VM_WRITE,
0,
process.th32ProcessID,
)
},
pid: process.th32ProcessID,
});
}
}
Err(_) => {
println!(
"Error converting process name for PID {}",
process.th32ProcessID
);
}
}
}
}
Err(ProcessErrorKind::UnknownProcess(name.into()).into())
}

impl Module {
pub fn read<T>(&self, offset: u32, parent: &GameProcess) -> Result<T> {
let mut read = unsafe { mem::MaybeUninit::uninit().assume_init() };
let mut amount_read: libc::size_t = 0;

if unsafe {
memoryapi::ReadProcessMemory(
*(&*parent).handle(),
(self.base + offset) as *const _,
&mut read as *mut _ as *mut _,
mem::size_of::<T>() as _,
&mut amount_read as *mut _,
)
} != (true as i32)
|| amount_read == 0
{
mem::forget(read);
return Err(ProcessErrorKind::MemoryRead(self.base + offset).into());
}

Ok(read)
pub fn read_address(&self, address: usize, size: usize) -> io::Result<Vec<u8>> {
let handle = self.pid.try_into_process_handle()?;
let bytes = copy_address(self.base_addr + address, size, &handle)?;
Ok(bytes)
}

pub fn write<T>(&mut self, parent: &GameProcess, offset: u32, mut value: T) -> Result<()> {
if unsafe {
memoryapi::WriteProcessMemory(
*(&*parent).handle(),
(self.base + offset) as *mut _,
&mut value as *mut _ as *mut _,
mem::size_of_val(&value),
std::ptr::null_mut(),
) as usize
} == 0
{
return Err(ProcessErrorKind::InvalidBytesWritten(self.base + offset).into());
}

pub fn write_address(&self, address: usize, bytes: Vec<u8>) -> io::Result<()> {
Ok(())
}
}
Loading

0 comments on commit 7069576

Please sign in to comment.