Better file format 1
This commit is contained in:
parent
f5cb818123
commit
b20846c797
3
analyzer/.vscode/settings.json
vendored
Normal file
3
analyzer/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"python.analysis.typeCheckingMode": "standard"
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
7
analyzer/format.txt
Normal file
7
analyzer/format.txt
Normal file
@ -0,0 +1,7 @@
|
||||
[entry point]
|
||||
[number of libraries]
|
||||
<Library> <Import1> <Import1Addr> <Import2> <Import2Addr> 00: Import the following things. (Terminate on 00)
|
||||
|
||||
[number of bytes in starting state as a uint32_t]
|
||||
00 [00-ff] <bytes>: Use the following 00-ff bytes literally
|
||||
[01-ff] <byte>: Repeat the next byte 02 to ff times
|
130
analyzer/main.py
130
analyzer/main.py
@ -1,80 +1,124 @@
|
||||
import base64
|
||||
from dataclasses import dataclass
|
||||
from io import BytesIO
|
||||
import json
|
||||
from typing import Generator
|
||||
import pefile
|
||||
|
||||
def main():
|
||||
subject = pefile.PE("subjects\\main.exe")
|
||||
@dataclass
|
||||
class Import:
|
||||
library: bytes
|
||||
procedures: list[tuple[bytes, int]]
|
||||
|
||||
def _single_or_none(x):
|
||||
items = [i for i in x]
|
||||
|
||||
@dataclass
|
||||
class Binary(object):
|
||||
starting_state: bytes
|
||||
entry_point: int
|
||||
imports: list[Import]
|
||||
|
||||
|
||||
def _single_or_none[T](ts: Generator[T]) -> T | None:
|
||||
items = [t for t in ts]
|
||||
if len(items) == 0:
|
||||
return None
|
||||
|
||||
assert len(items) == 1
|
||||
if len(items) == 1:
|
||||
return items[0]
|
||||
|
||||
def _dump(fname, section):
|
||||
with open(fname, "wb") as f:
|
||||
if section is not None:
|
||||
if isinstance(section, bytes):
|
||||
f.write(section)
|
||||
else:
|
||||
f.write(section.get_data())
|
||||
raise ValueError(f"expected 1 or 0, got {len(items)}")
|
||||
|
||||
for i in subject.sections:
|
||||
print(i)
|
||||
def _single[T](ts: Generator[T]) -> T:
|
||||
items = [t for t in ts]
|
||||
if len(items) == 1:
|
||||
return items[0]
|
||||
|
||||
text_section = _single_or_none(i for i in subject.sections if i.Name == b".text\0\0\0")
|
||||
raise ValueError(f"expected 1, got {len(items)}")
|
||||
|
||||
|
||||
def _create_binary(subject: pefile.PE) -> Binary:
|
||||
optional_header = subject.OPTIONAL_HEADER
|
||||
assert isinstance(optional_header, pefile.Structure)
|
||||
text_section = _single(i for i in subject.sections if i.Name == b".text\0\0\0")
|
||||
data_section = _single_or_none(i for i in subject.sections if i.Name == b".data\0\0\0")
|
||||
rdata_section = _single_or_none(i for i in subject.sections if i.Name == b".rdata\0\0")
|
||||
|
||||
_dump("dumps\\text.dat", text_section)
|
||||
_dump("dumps\\data.dat", data_section)
|
||||
_dump("dumps\\rdata.dat", rdata_section)
|
||||
|
||||
relevant_sections = [section for section in (text_section, data_section, rdata_section) if section is not None]
|
||||
if len(relevant_sections) == 0:
|
||||
raise ValueError("no sections to plot")
|
||||
print([(i.VirtualAddress, i) for i in relevant_sections])
|
||||
min_address = min(i.VirtualAddress for i in relevant_sections)
|
||||
max_address = max(_round_up_to_page(i.VirtualAddress + i.SizeOfRawData) for i in relevant_sections)
|
||||
|
||||
print(min_address, max_address)
|
||||
buffer = bytearray(max_address - min_address)
|
||||
for section in relevant_sections:
|
||||
data = section.get_data() # TODO: De-pad the text section from 0xccs
|
||||
start = section.VirtualAddress - min_address
|
||||
buffer[start:start+len(data)] = data
|
||||
buffer = bytes(buffer)
|
||||
|
||||
_dump("dumps\\starting_state.dat", buffer)
|
||||
starting_state = bytes(buffer)
|
||||
|
||||
binary = {
|
||||
"startingState": base64.b64encode(buffer).decode("utf8"),
|
||||
"imports": [],
|
||||
}
|
||||
entry_point_rva = getattr(optional_header, "AddressOfEntryPoint")
|
||||
print(entry_point_rva)
|
||||
entry_point = (entry_point_rva - min_address)
|
||||
|
||||
# find imports
|
||||
# print(subject)
|
||||
# print(dir(subject))
|
||||
for entry in subject.DIRECTORY_ENTRY_IMPORT:
|
||||
|
||||
# print(entry.dll)
|
||||
imports: list[Import] = []
|
||||
for entry in getattr(subject, "DIRECTORY_ENTRY_IMPORT"):
|
||||
library: bytes = entry.dll
|
||||
procedures: list[tuple[bytes, int]] = []
|
||||
for imp in entry.imports:
|
||||
# print(dir(imp))
|
||||
import_address = imp.address - subject.OPTIONAL_HEADER.ImageBase - min_address
|
||||
print(hex(import_address), imp.name)
|
||||
binary["imports"].append({
|
||||
"dll": entry.dll.decode("utf8"),
|
||||
"symbol": imp.name.decode("utf8"),
|
||||
"address": import_address,
|
||||
})
|
||||
import_address_rva = imp.address - getattr(optional_header, "ImageBase")
|
||||
import_address = import_address_rva - min_address
|
||||
procedures.append((imp.name, import_address))
|
||||
|
||||
entry_point_rva = subject.OPTIONAL_HEADER.AddressOfEntryPoint
|
||||
binary["entryPoint"] = entry_point_rva - min_address
|
||||
with open("binaries/main.json", "wt") as f:
|
||||
f.write(json.dumps(binary, indent=4))
|
||||
imports.append(Import(library, procedures))
|
||||
|
||||
return Binary(
|
||||
starting_state=starting_state,
|
||||
entry_point=entry_point,
|
||||
imports=imports,
|
||||
)
|
||||
|
||||
|
||||
def _encode_binary(binary: Binary) -> bytes:
|
||||
out = BytesIO()
|
||||
|
||||
def _write_u32(n: int):
|
||||
out.write(n.to_bytes(4, "little", signed=False))
|
||||
|
||||
def _write_u8(n: int):
|
||||
out.write(n.to_bytes(1, "little", signed=False))
|
||||
|
||||
def _write_zt(s: bytes):
|
||||
out.write(s)
|
||||
_write_u8(0)
|
||||
|
||||
_write_u32(binary.entry_point)
|
||||
for i in binary.imports:
|
||||
print(i.library)
|
||||
_write_zt(i.library)
|
||||
print(i.procedures)
|
||||
for (procedure, address) in i.procedures:
|
||||
_write_zt(procedure)
|
||||
_write_u32(address)
|
||||
_write_u8(0)
|
||||
_write_u8(0)
|
||||
|
||||
_write_u32(len(binary.starting_state))
|
||||
# TODO: No RLE for now
|
||||
for b in binary.starting_state:
|
||||
_write_u8(b)
|
||||
|
||||
return out.getbuffer()
|
||||
|
||||
def main():
|
||||
subject = pefile.PE("subjects\\main.exe")
|
||||
|
||||
binary = _create_binary(subject)
|
||||
code = _encode_binary(binary)
|
||||
with open("binaries\\main.dat", "wb") as f:
|
||||
f.write(code)
|
||||
|
||||
def _round_up_to_page(x: int):
|
||||
# TODO: Is this the page size on x64? I think it is
|
||||
|
4
analyzer/poetry.lock
generated
4
analyzer/poetry.lock
generated
@ -13,5 +13,5 @@ files = [
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.10"
|
||||
content-hash = "6f28e4dc3bf3b09c57354693b75dc7975b70a7aac2ee7c83fc81b0058520d7f9"
|
||||
python-versions = "^3.13"
|
||||
content-hash = "8e680dad2071f9d7a37ca34d4fd6da67ba3922e0de45f0442c7b38d07f8fa9f0"
|
||||
|
@ -6,7 +6,7 @@ authors = ["Nyeogmi <economicsbat@gmail.com>"]
|
||||
readme = "README.md"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.10"
|
||||
python = "^3.13"
|
||||
pefile = "^2024.8.26"
|
||||
|
||||
|
||||
|
482
runner/Cargo.lock
generated
482
runner/Cargo.lock
generated
@ -2,261 +2,6 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362"
|
||||
dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"log",
|
||||
"wasm-bindgen",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown 0.12.3",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.15.2",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.77"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.172"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.95"
|
||||
@ -279,26 +24,10 @@ dependencies = [
|
||||
name = "runner"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_bytes",
|
||||
"serde_json",
|
||||
"serde_with",
|
||||
"windows-sys",
|
||||
"winres",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.219"
|
||||
@ -308,15 +37,6 @@ dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_bytes"
|
||||
version = "0.11.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.219"
|
||||
@ -328,60 +48,6 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.140"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "3.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"chrono",
|
||||
"hex",
|
||||
"indexmap 1.9.3",
|
||||
"indexmap 2.9.0",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"serde_with_macros",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with_macros"
|
||||
version = "3.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.100"
|
||||
@ -393,37 +59,6 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"num-conv",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49"
|
||||
dependencies = [
|
||||
"num-conv",
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.11"
|
||||
@ -439,123 +74,6 @@ version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"rustversion",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.61.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-link",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
|
@ -4,10 +4,6 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
serde = {version = "1.0.219", features=["derive"]}
|
||||
serde_bytes = "0.11.17"
|
||||
serde_json = "1.0.140"
|
||||
serde_with = {version="3.12.0", features=["base64"]}
|
||||
windows-sys = {version="0.59.0", features=["Win32_System_Memory", "Win32_System_LibraryLoader", "Win32_System_Diagnostics_ToolHelp", "Win32_System_Threading", "Win32_System_Diagnostics_Debug", "Win32_Security"]}
|
||||
|
||||
[build-dependencies]
|
||||
|
BIN
runner/binaries/main.dat
Normal file
BIN
runner/binaries/main.dat
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
@ -1,14 +1,11 @@
|
||||
use core::str;
|
||||
use std::ffi::{c_void, CStr};
|
||||
use std::marker::PhantomData;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ptr;
|
||||
use std::{fs::File, io::Read};
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde_with::base64::{Base64, Standard};
|
||||
use serde_with::formats::Padded;
|
||||
use serde_with::serde_as;
|
||||
|
||||
use windows_sys::Win32::Foundation::{GetLastError, PROC};
|
||||
use windows_sys::Win32::Foundation::GetLastError;
|
||||
use windows_sys::Win32::System::Diagnostics::Debug;
|
||||
use windows_sys::Win32::System::Diagnostics::ToolHelp::{self, PROCESSENTRY32};
|
||||
use windows_sys::Win32::System::Memory;
|
||||
@ -18,30 +15,35 @@ use windows_sys::Win32::System::{LibraryLoader, Threading};
|
||||
const LOAD_LIBRARY_A: *const c_void = LibraryLoader::LoadLibraryA as *const c_void;
|
||||
const GET_PROC_ADDRESS: *const c_void = LibraryLoader::GetProcAddress as *const c_void;
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Import {
|
||||
#[serde(with = "serde_bytes")]
|
||||
dll: Vec<u8>,
|
||||
#[serde(with = "serde_bytes")]
|
||||
symbol: Vec<u8>,
|
||||
address: usize,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Binary {
|
||||
#[serde(rename = "startingState")]
|
||||
#[serde_as(as = "Base64<Standard, Padded>")]
|
||||
starting_state: Vec<u8>,
|
||||
imports: Vec<Import>,
|
||||
#[serde(rename = "entryPoint")]
|
||||
entry_point: usize,
|
||||
}
|
||||
fn main() {
|
||||
unsafe { _main_remote() }
|
||||
}
|
||||
|
||||
struct Reader<'a> {
|
||||
phantom: PhantomData<&'a [u8]>,
|
||||
ptr: *const u8,
|
||||
}
|
||||
|
||||
impl<'a> Reader<'a> {
|
||||
unsafe fn read<T: Copy>(&mut self) -> T {
|
||||
let value = core::ptr::read_unaligned(self.ptr as *const T);
|
||||
self.ptr = self.ptr.byte_add(core::mem::size_of::<T>());
|
||||
value
|
||||
}
|
||||
|
||||
unsafe fn read_zt(&mut self) -> &'a [u8] {
|
||||
let start = self.ptr;
|
||||
let mut n = 0;
|
||||
while *self.ptr != 0 {
|
||||
self.ptr = self.ptr.byte_add(1);
|
||||
n += 1
|
||||
}
|
||||
self.ptr = self.ptr.byte_add(1);
|
||||
n += 1; // include the null terminator
|
||||
return std::slice::from_raw_parts(start, n);
|
||||
}
|
||||
}
|
||||
|
||||
struct LocalWriter {
|
||||
binary: *mut u8,
|
||||
base: *mut u8,
|
||||
@ -64,12 +66,6 @@ trait CodeGen {
|
||||
unsafe fn address_in_binary(&mut self, offset: usize) -> *const c_void;
|
||||
}
|
||||
|
||||
impl Measurer {
|
||||
fn round_up(&mut self) {
|
||||
self.count = (self.count + 15) / 16 * 16;
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeGen for LocalWriter {
|
||||
unsafe fn write(&mut self, u8s: &[u8]) -> *const c_void {
|
||||
let addr = self.ptr;
|
||||
@ -91,82 +87,109 @@ impl CodeGen for Measurer {
|
||||
return ptr::null();
|
||||
}
|
||||
|
||||
unsafe fn address_in_binary(&mut self, offset: usize) -> *const c_void {
|
||||
unsafe fn address_in_binary(&mut self, _: usize) -> *const c_void {
|
||||
return ptr::null();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn write_imports(
|
||||
strings: &mut impl CodeGen,
|
||||
code: &mut impl CodeGen,
|
||||
original_entry_point: usize,
|
||||
imports: &[Import],
|
||||
prelude: &mut impl CodeGen,
|
||||
reader: &mut Reader,
|
||||
) {
|
||||
let entry_point = reader.read::<u32>();
|
||||
println!("entry point: {}", entry_point);
|
||||
// push rbp
|
||||
code.write(&[0x55]);
|
||||
prelude.write(&[0x55]);
|
||||
// mov rbp, rsp
|
||||
code.write(&[0x48, 0x89, 0xe5]);
|
||||
prelude.write(&[0x48, 0x89, 0xe5]);
|
||||
// nop
|
||||
code.write(&[0x90]);
|
||||
prelude.write(&[0x90]);
|
||||
// sub rsp, 0x20
|
||||
code.write(&[0x48, 0x83, 0xec, 0x20]);
|
||||
prelude.write(&[0x48, 0x83, 0xec, 0x20]);
|
||||
|
||||
// windows needs 32 bytes to clobber: https://en.wikipedia.org/wiki/X86_calling_conventions#Microsoft_x64_calling_convention
|
||||
for import in imports {
|
||||
let library_addr = strings.write(&import.dll);
|
||||
strings.write(&[0]);
|
||||
let symbol_addr = strings.write(&import.symbol);
|
||||
loop {
|
||||
let dll = reader.read_zt();
|
||||
if dll.len() == 1 {
|
||||
break;
|
||||
}
|
||||
println!("import dll: {:?}", str::from_utf8(dll).unwrap());
|
||||
let library_addr = strings.write(dll);
|
||||
strings.write(&[0]);
|
||||
|
||||
loop {
|
||||
let symbol = reader.read_zt();
|
||||
if symbol.len() == 1 {
|
||||
break;
|
||||
}
|
||||
println!("import symbol: {:?}", str::from_utf8(symbol).unwrap());
|
||||
|
||||
let dest = reader.read::<u32>();
|
||||
let symbol_addr = strings.write(symbol);
|
||||
|
||||
// mov rcx, library name
|
||||
code.write(&[0x48, 0xb9]);
|
||||
code.write_ptr(library_addr);
|
||||
prelude.write(&[0x48, 0xb9]);
|
||||
prelude.write_ptr(library_addr);
|
||||
// mov rax, LoadLibraryA
|
||||
code.write(&[0x48, 0xb8]);
|
||||
code.write_ptr(LOAD_LIBRARY_A);
|
||||
prelude.write(&[0x48, 0xb8]);
|
||||
prelude.write_ptr(LOAD_LIBRARY_A);
|
||||
// call rax
|
||||
code.write(&[0xff, 0xd0]);
|
||||
prelude.write(&[0xff, 0xd0]);
|
||||
|
||||
// mov rcx, rax
|
||||
code.write(&[0x48, 0x89, 0xc1]);
|
||||
prelude.write(&[0x48, 0x89, 0xc1]);
|
||||
// mov rdx, symbol name
|
||||
code.write(&[0x48, 0xba]);
|
||||
code.write_ptr(symbol_addr);
|
||||
prelude.write(&[0x48, 0xba]);
|
||||
prelude.write_ptr(symbol_addr);
|
||||
// mov rax, GetProcAddress
|
||||
code.write(&[0x48, 0xb8]);
|
||||
code.write_ptr(GET_PROC_ADDRESS);
|
||||
prelude.write(&[0x48, 0xb8]);
|
||||
prelude.write_ptr(GET_PROC_ADDRESS);
|
||||
// call rax
|
||||
code.write(&[0xff, 0xd0]);
|
||||
prelude.write(&[0xff, 0xd0]);
|
||||
// mov [import address], rax
|
||||
code.write(&[0x48, 0xa3]);
|
||||
let addr = code.address_in_binary(import.address);
|
||||
code.write_ptr(addr);
|
||||
prelude.write(&[0x48, 0xa3]);
|
||||
let addr = prelude.address_in_binary(dest as usize);
|
||||
prelude.write_ptr(addr);
|
||||
}
|
||||
}
|
||||
// mov rax, original entry point
|
||||
code.write(&[0x48, 0xb8]);
|
||||
let addr = code.address_in_binary(original_entry_point);
|
||||
prelude.write(&[0x48, 0xb8]);
|
||||
let addr = prelude.address_in_binary(entry_point as usize);
|
||||
// let addr = load_library_a;
|
||||
code.write_ptr(addr);
|
||||
prelude.write_ptr(addr);
|
||||
// call rax
|
||||
code.write(&[0xff, 0xd0]);
|
||||
prelude.write(&[0xff, 0xd0]);
|
||||
// leave, ret
|
||||
code.write(&[0xc9, 0xc3]);
|
||||
prelude.write(&[0xc9, 0xc3]);
|
||||
}
|
||||
|
||||
unsafe fn write_starting_state(binary: *mut u8, reader: &mut Reader) {
|
||||
let length = reader.read::<u32>() as usize;
|
||||
let ptr = reader.ptr;
|
||||
println!("length: {:?}", length);
|
||||
|
||||
binary.copy_from(ptr, length);
|
||||
}
|
||||
|
||||
unsafe fn _main_remote() {
|
||||
let mut input = File::open("binaries/main.json").unwrap();
|
||||
let mut input = File::open("binaries/main.dat").unwrap();
|
||||
let mut buf: Vec<u8> = vec![];
|
||||
let _ = input.read_to_end(&mut buf).unwrap();
|
||||
|
||||
let binary = serde_json::from_slice::<Binary>(&buf).unwrap();
|
||||
|
||||
let mut measuring_reader = Reader {
|
||||
phantom: PhantomData,
|
||||
ptr: buf.as_ptr(),
|
||||
};
|
||||
let mut string_measurer = Measurer { count: 0 };
|
||||
let mut code_measurer = Measurer { count: 0 };
|
||||
write_imports(
|
||||
&mut string_measurer,
|
||||
&mut code_measurer,
|
||||
binary.entry_point,
|
||||
&binary.imports,
|
||||
&mut measuring_reader,
|
||||
);
|
||||
let starting_state_len = measuring_reader.read::<u32>() as usize;
|
||||
println!("starting state len: {}", starting_state_len);
|
||||
// string_measurer.round_up();
|
||||
// code_measurer.round_up();
|
||||
|
||||
@ -180,7 +203,7 @@ unsafe fn _main_remote() {
|
||||
println!("got null");
|
||||
return;
|
||||
}
|
||||
let total_size = binary.starting_state.len() + string_measurer.count + code_measurer.count;
|
||||
let total_size = starting_state_len as usize + string_measurer.count + code_measurer.count;
|
||||
let remote_address_space = Memory::VirtualAllocEx(
|
||||
remote,
|
||||
ptr::null(),
|
||||
@ -195,12 +218,12 @@ unsafe fn _main_remote() {
|
||||
Memory::PAGE_EXECUTE_READWRITE,
|
||||
);
|
||||
|
||||
local_address_space.copy_from(
|
||||
binary.starting_state.as_ptr() as *const c_void,
|
||||
binary.starting_state.len(),
|
||||
);
|
||||
let mut loading_reader = Reader {
|
||||
phantom: PhantomData,
|
||||
ptr: buf.as_ptr(),
|
||||
};
|
||||
|
||||
let strings = local_address_space.byte_add(binary.starting_state.len());
|
||||
let strings = local_address_space.byte_add(starting_state_len);
|
||||
let prelude = strings.byte_add(string_measurer.count);
|
||||
let mut strings_writer = LocalWriter {
|
||||
binary: remote_address_space as *mut u8,
|
||||
@ -212,12 +235,15 @@ unsafe fn _main_remote() {
|
||||
base: local_address_space as *mut u8,
|
||||
ptr: prelude as *mut u8,
|
||||
};
|
||||
println!("writing imports");
|
||||
write_imports(
|
||||
&mut strings_writer,
|
||||
&mut prelude_writer,
|
||||
binary.entry_point,
|
||||
&binary.imports,
|
||||
&mut loading_reader,
|
||||
);
|
||||
println!("writing starting state");
|
||||
write_starting_state(local_address_space as *mut u8, &mut loading_reader);
|
||||
println!("done!");
|
||||
println!("error: {}", GetLastError());
|
||||
println!(
|
||||
"Copying memory to foreign process (at {:?} from {:?} get {:?})",
|
||||
@ -234,7 +260,7 @@ unsafe fn _main_remote() {
|
||||
println!("Creating remote thread");
|
||||
|
||||
let entry_point =
|
||||
remote_address_space.byte_add(binary.starting_state.len() + string_measurer.count);
|
||||
remote_address_space.byte_offset(prelude.byte_offset_from(local_address_space));
|
||||
println!("Entry point: {:?}", entry_point);
|
||||
Threading::CreateRemoteThread(
|
||||
remote,
|
||||
@ -269,56 +295,3 @@ unsafe fn identify_victim() -> Option<u32> {
|
||||
}
|
||||
return None;
|
||||
}
|
||||
/*
|
||||
unsafe fn _main_local() {
|
||||
let mut input = File::open("binaries/main.json").unwrap();
|
||||
let mut buf: Vec<u8> = vec![];
|
||||
let _ = input.read_to_end(&mut buf).unwrap();
|
||||
|
||||
let binary = serde_json::from_slice::<Binary>(&buf).unwrap();
|
||||
|
||||
let mut string_measurer = Measurer { count: 0 };
|
||||
let mut code_measurer = Measurer { count: 0 };
|
||||
write_imports(
|
||||
&mut string_measurer,
|
||||
&mut code_measurer,
|
||||
binary.entry_point,
|
||||
&binary.imports,
|
||||
);
|
||||
|
||||
// TODO: Alignment
|
||||
let address_space = Memory::VirtualAlloc(
|
||||
ptr::null(),
|
||||
binary.starting_state.len() + string_measurer.count + code_measurer.count,
|
||||
Memory::MEM_COMMIT | Memory::MEM_RESERVE,
|
||||
Memory::PAGE_EXECUTE_READWRITE,
|
||||
);
|
||||
|
||||
address_space.copy_from(
|
||||
binary.starting_state.as_ptr() as *const c_void,
|
||||
binary.starting_state.len(),
|
||||
);
|
||||
|
||||
let strings = address_space.byte_add(binary.starting_state.len());
|
||||
let prelude = strings.byte_add(string_measurer.count);
|
||||
let mut strings_writer = LocalWriter {
|
||||
binary: address_space as *mut u8,
|
||||
ptr: strings as *mut u8,
|
||||
};
|
||||
let mut prelude_writer = LocalWriter {
|
||||
binary: address_space as *mut u8,
|
||||
ptr: prelude as *mut u8,
|
||||
};
|
||||
write_imports(
|
||||
&mut strings_writer,
|
||||
&mut prelude_writer,
|
||||
binary.entry_point,
|
||||
&binary.imports,
|
||||
);
|
||||
|
||||
let function: unsafe extern "C" fn() -> *const c_void = std::mem::transmute(prelude);
|
||||
|
||||
let result = function();
|
||||
}
|
||||
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user