Last active
December 24, 2015 00:59
-
-
Save zbroyar/6720528 to your computer and use it in GitHub Desktop.
Пошук та модифікація значень у адресному просторі процесів OS X.В оригіналі призначено для хаку ресурсів у грі "XCOM: Enemy Unknown".
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(* ocamlfind ocamlopt -o scan -package unix,pcre scan.ml -linkpkg | |
Якщо знайти адресу кількості трупів сектоїдів, то забити склад | |
ніштяками можна, наприклад, так: | |
let addr = $sectoids | |
and pid = <XCOM pid> | |
and ch = open_out "cmd.gdb" in | |
for i = 0 to 35 do | |
Printf.fprintf ch "set {int}(0x%X + 4*%d) = 99999\n" addr i | |
done; | |
close_out ch; | |
sudo gdb --batch --command=cmd.dbg -p $pid 2>/dev/null | |
Див.: http://blog.mykola.org/post/62362762627/xcom-enemy-unknown | |
*) | |
open Printf | |
(*------------------------------------------------------------------------------ | |
* Модулі та типи | |
-----------------------------------------------------------------------------*) | |
module S = Set.Make(struct type t = int let compare = compare end) | |
(*------------------------------------------------------------------------------ | |
* Допоміжні функи | |
-----------------------------------------------------------------------------*) | |
let ($) f x = f x | |
let (%) f g = fun x -> f (g x) | |
let rec fold_channel_lines f r ch = | |
let s = try Some (input_line ch) with End_of_file -> None in | |
match s with | |
Some s -> | |
let r = | |
try f r s | |
with Not_found -> printf "Invalid line: %s\n%!" s; r in | |
fold_channel_lines f r ch | |
| None -> close_in ch; r | |
(*------------------------------------------------------------------------------ | |
* Бізнес-логіка :-] | |
-----------------------------------------------------------------------------*) | |
let find_addresses pid sections value = | |
let fname = sprintf "tmp.gdb.%d" pid in | |
let cmd = sprintf "gdb --batch --command=%s -p %d" fname pid | |
and ch = open_out fname in | |
List.iter (fun (s,e) -> fprintf ch "find /w 0x%x, 0x%x, %d\n" s e value) sections; | |
close_out ch; | |
let rex = Pcre.regexp "^(0x[^[:space:]]+)$" | |
and ch = Unix.open_process_in cmd in | |
let set = fold_channel_lines | |
(fun set str -> | |
try | |
let subst = Pcre.exec ~rex str in | |
let addr = int_of_string % Pcre.get_substring subst $ 1 in | |
S.add addr set | |
with Not_found -> set | |
) S.empty ch in | |
ignore % Unix.system % sprintf "rm %s" $ fname; set | |
let modify pid addr value = | |
let cmd = sprintf "gdb --batch -ex \"set {int}0x%x = %d\" -p %d 2>/dev/null" | |
addr value pid in | |
ignore % Unix.system $ cmd | |
let rec loop ?(found = false) pid sections addresses = | |
printf "Нове значення? "; | |
let new_addresses = find_addresses pid sections (read_int()) in | |
let res = S.inter addresses new_addresses in | |
let count = S.cardinal res in | |
printf "Адрес: %d\n%!" count; | |
match count, found with | |
| 1,false -> | |
printf "Знайдено адресу: 0x%X\nКонтрольна ітерація.\n%!" | |
(List.hd % S.elements $ res); | |
loop ~found:true pid sections res | |
| 1, true -> | |
printf "Підтверджено! Модифікуємо? "; | |
begin | |
match read_line () with | |
| "yes" | "Yes" | "YES" | "так" | "Так" | "ТАК" -> | |
printf "Скільки ставимо? "; | |
modify pid | |
(List.hd % S.elements $ res) | |
(read_int ()) | |
| _ -> printf "Ну добре. До побачення" | |
end | |
| 0, _ -> printf "Облом. Схоже, метод не працює...\n%!" | |
| _ -> loop pid sections res | |
(*------------------------------------------------------------------------------ | |
* Головна частина | |
-----------------------------------------------------------------------------*) | |
let pid = int_of_string Sys.argv.(1) | |
let sections = | |
let s2i s = Scanf.sscanf s "%16x" (fun x -> x) in | |
let sections_command = sprintf "vmmap %d" pid in | |
let ch = Unix.open_process_in sections_command | |
and rex = Pcre.regexp "^.* ([[:xdigit:]]+)-([[:xdigit:]]+) .*$" in | |
let res = fold_channel_lines | |
(fun res str -> | |
(*printf "%s ... " str;*) | |
try | |
let subst = Pcre.exec ~rex str in | |
let r_start = s2i % Pcre.get_substring subst $ 1 | |
and r_end = s2i % Pcre.get_substring subst $ 2 in | |
(*printf "0x%X -> 0x%X ... OK\n%!" r_start r_end;*) | |
(r_start, r_end) :: res | |
with Not_found -> (*printf "ignored\n%!";*) res | |
) [] $ ch in | |
List.sort compare res | |
let initial_addresses = | |
printf "Cекцій: %d\n%!" % List.length $ sections; | |
printf "Початкове значення? "; | |
find_addresses pid sections (read_int ()) | |
let _ = | |
printf "Адрес: %d\n%!" (S.cardinal initial_addresses); | |
loop pid sections initial_addresses |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment