From b20846c797fc551c5e8b40de6655d9e7b557d6b6 Mon Sep 17 00:00:00 2001 From: Nyeogmi Date: Fri, 25 Apr 2025 21:30:11 -0700 Subject: [PATCH] Better file format 1 --- analyzer/.vscode/settings.json | 3 + .../starting_state.dat => binaries/main.dat} | Bin 20480 -> 20540 bytes analyzer/dumps/data.dat | Bin 5120 -> 0 bytes analyzer/dumps/rdata.dat | Bin 512 -> 0 bytes analyzer/dumps/text.dat | Bin 512 -> 0 bytes analyzer/format.txt | 7 + analyzer/main.py | 134 +++-- analyzer/poetry.lock | 4 +- analyzer/pyproject.toml | 2 +- runner/Cargo.lock | 482 ------------------ runner/Cargo.toml | 4 - runner/binaries/main.dat | Bin 0 -> 20540 bytes runner/binaries/main.json | 16 - runner/src/main.rs | 249 ++++----- 14 files changed, 213 insertions(+), 688 deletions(-) create mode 100644 analyzer/.vscode/settings.json rename analyzer/{dumps/starting_state.dat => binaries/main.dat} (95%) delete mode 100644 analyzer/dumps/data.dat delete mode 100644 analyzer/dumps/rdata.dat delete mode 100644 analyzer/dumps/text.dat create mode 100644 analyzer/format.txt create mode 100644 runner/binaries/main.dat delete mode 100644 runner/binaries/main.json diff --git a/analyzer/.vscode/settings.json b/analyzer/.vscode/settings.json new file mode 100644 index 0000000..8aef7b1 --- /dev/null +++ b/analyzer/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.analysis.typeCheckingMode": "standard" +} \ No newline at end of file diff --git a/analyzer/dumps/starting_state.dat b/analyzer/binaries/main.dat similarity index 95% rename from analyzer/dumps/starting_state.dat rename to analyzer/binaries/main.dat index 1fcaf25cffdf5454aeccef632d99cd2746ac0444..18c91172a63d1c0c10301210e7cd6a73c8f3f1b1 100644 GIT binary patch delta 69 zcmZozz_@1tqYVQPc)JGqx%wCz>80f4Fa+nMrWUwXFf<4NWx_rEe0{;f0Xd14!TF_m QDGU=p5)2Fh3=9hb0Fwt20ssI2 delta 9 Qcmdn9fU#i#<3gJN02F%ztN;K2 diff --git a/analyzer/dumps/data.dat b/analyzer/dumps/data.dat deleted file mode 100644 index 401022a0b88dddda5aa8b6048b9f12554cdde1b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5120 zcmd6rX*8Q_*T?S+B<6^r5voZI2Q?&wQq{&3RMe2Dp{j`x6*^GG=_CY2X=_fjG^kly zN?UXaLJgs6s`hBhp^mAgJ)H-6;(6Z>&xiB%S?~M*aPPhE57*k)Z~fQW`@VhLNF=rj z0QlMOb7mfn#b^Tn;0u5N;uZklD**rz3;^Go^QPw6=aAk}HS&X49b!iL7}`LzgF)cM zPIPi$N!g)|_;jI{QHMxB-U2oC-RHQ4q9{uS2Zwicdd;*FL6nC0;A^EUAp>q-@|5UU z%kIiaVS2^gUX8LdI|{e&M6CI1XB!729}Ro|Iy+MUyM8b3L&1OnF7pZTL~W&+<#Q*O zeebsK$$NRVG9p@zIx&}f&%5r<*L9J*@exL@&6(bxJ#q69A^XH{EDs$OAbEA}>Uzkp zcj9AK1-Or}Ug7?tZI2t=D-h%EmSXXDPw_8bvG~U_U(m5e^P)lNYoKJ3w5%cwj+Pj{D=Ldg+tS4rT$JVp{8H?+>dB44Gboo@6xg>~)2GkYF{X`}5|@ zy2Ds6#Di*6Qjtb{+yu6^=uAiT16zgLtw)$IGeocZ7;WL!riQdT88!9v#r@{t>*)yr6aGr5n_r>^wZl0T}^4i~xxe0&gpDT3H4sA{RZ05Ef_HL&r z3@6+S>@ZJvRyP8B0pOz&1N~dyB3l<*s(71^Ue;9x2t~P&4L;h=j9anZ>;+KCB_aQ@ zzNbd(qD6Pmx*$(MBLT$rVxw?du~3no)QhE8{v^08R34-vGS|!sw^cBbl7l6&0W4bp zSSwLfKmy7Z&fjwLj{f&@e<>G+CQ*u#9hM5)kt`NPnkYc}s6sPk%E}Y8$Xt2I_4Hl)A3n%FqV+c6 znHVZGNsOttes{pdX=%wjNZx~h<*o-EeUmfxgDSfCz1aIEcL)kfhnq^Kxnhhy2ikvg5- zqoqY>_sVBFngxlERiD%*#ZBcaKRsJ<{6o;EkeH9{gS?>bWh#o|ZnB){>6cgZ#o7I6 zVa(T_+u2uauSfb^i9d3)|1Gti;xGIXbM?{Zwj-66uvwq`<8PKWc>ML&g$mTcO`upi zv`;3`zCU-JmrTRo23-ih0f~;k`rD@=Qe7Yn?H1Q-3i9F9VgqIyl@9@?VfbMrR8FVJ~dimo%67ljV zm;yFk`8?ewqilGsM@E^v87@WCV>=WWCgpig#YE^nnaux??w2G-j6kaDsn(bvM_~ba zIiG2D(4Utx+cI8Gsl?Uq4?8{M;X=qTkIfIFpYUnHPv^N51vobHHW}&~z1f;FzH#T( zpQt}7uXU~Umpl(mb~&8ZrZ(H;f7VPpZDlN`G~+KOa+Som=tzlvE?XKo&4$CF7XX1* z5I}d3u^>(u>x)>8yoWG-N`#i`2A{n)%egcFh8hn(V$N%noA(aq>Ynx2MLC6rUJA%e zBOTb4czzfg< zQx6x^w#G!%w8je6%XI{Wy^s$^1yqNYw=(TlzT7)V>tGezk@jI7$BU>3N1xxBaeN#l zvYG6juqRM2>>7BaVo;Jh#*!Iu-P_JP)gQIzTeabAJilrX8&kPveCK{4(Nk7}83jiDp}SL6uAYbgnBTBXwBOfLR?r|=%ID#ry@4^{Jy=bJP3dx z-yiB=%-UXqT%Jvu5#ZS!HCClEYTKwH={t(0LedWN=&iaTg^EtHuKndH(Bx?U^xk|T znN?y-UN778tEO_Po^jR7+K{&M`L;cFB=4;O#U$5B7QMkaG(AHZqhL(5(dje3Hmv?5 z=g!corOW4*?Urs^a;Z6kM})Ty>ZjlTU|p$Mi%Bl`F0!9t-kMa_E0U)*Ag`OItAe3Y z+#0LUTN;J#`cOwM`7|pdpa)s?L>GMp6F94#2O7#F$YhOV;+moWSM!=RG1=~=iuS8d8HeCu3Mif^_TePeS>Xb(AV?li_6v@jdO!4$hRU-=;=n^c(CH* zfgBf=YERxjXsmVhT3c{xbHb;2*q@ct^Aj^Qnb5lVV zUVRy6Psnj~s`3qi#D^lrf9J_P%3TT0wZ@M4OYs4y+oyhdC*2!AO)<2#{PVch>~W^|NAU*ls50rBK^wW1HLfywyO%6e&Qj z<8Xd0X7r4&dPE9QUrU1#Ym~ygO)d-d0DaQeI9&lxPJ=?c+K3PjT4-=0;>kU9U za^ARWaDrPKZtVI*yj9KIwwaz&#N4&IUBgM|d8o#YpOogp_swowEm-gHi1aQq<2mH? z1|Ko0zK$qazXg4KQeS}BWm4NfSg@j`aJ%=)3v=9LSgX_OtMRdss-xJL$*>d7#pD~o zz3A`9Z9IMu*rh#sVXZ>`wHJXG(A{#t#EZ6U)9~@rJ7fd3WC6}*FK>A*1)OzD_q12J zt7}boW5lX{0gs+l8>trO|D;2)rG8ZeZ&XtpxS6{^r87`VeFZ9<^uga7 zI$?uh#}bueWm7ZD8oh*Zzsk<-Z1-GihhI2X(xR^9|hg^<-<&ycN`)#uWBR$`W`#1P}adMRKfmy9guN)AvqTVx?+WaYa&g3q| zdp}nmjNDbcoH?Lp81|HO>B(qqKj(D@BhDRlrqFCt(-}L3e*ZgBI%Apg^!kXVB(_p6 z@y_Ch8zd-64OXP38VR@3z!9XCc`bpF9c@_y^NuKP)N};z+eM|GR4WC_pd839hTJj7 zk&@ENBbJa?f-N%0{TRM$L+3R?r(2E#P4K*Aj8yEwqn)JR#>oVRm)V@tPU}XZ#-?a7 zNM%TJdYo+1rd~ktI@mF6=%;%U2KqQ$ZqZy_5%EGGs+1AEiM+w|26Z6S?l-AZwQl9w zoOl=&Q8d7xm>=ACo-aDEK+iW$b%#7)JviMe+bNpXf4`cjYrecZQ)4mT!W~@N;PcJR zv5o*DP6LaPQJJduuPtdpEUVp+<1%nCELzQEM>~fv^kZe!dN#$Mg+?^iXiS_7TNGnW z)>D+uiMs^=KoN@*B;R(bN46iq8@#yYyP$&slRywKNaFvwhek;xDd4&>60~axr3eCH zh-=ogMguxZO9mp3l1jlQrIxv62%e_s_f=HS6zCwb06AbU7Ye~a zl?@1@05y3{(?OPz=v6wEN0o&EhrZGpRq4lww2Zx>fq_hP>mjOo2riSUL7+cB8^Rr7 zD945xw$dUnA(&1DXchu2;N#;4H5AB2p=2v%`5sO3)y?w$_zs=E9LypIGfaz-1r0dS za!l!qs=D5&30v+4pTENY?$iaPE&xJ*UV=Lh^&9tyCdwF)0a$@xX(7;*M1&KiFX)Zp zxDaBpKn;jRqNFA3vy2Z)xz3*W6kGIx4Fyd1=vJnfD}tyX1f@(<3LxF27ocRND?>mv zl)bysQXfZasI;~@u)Uywyqq%;I}IB0&;bCPmjs!L0S##YYKU#`Ll!I^s;Heuf$@)z z2{67GXCec_Rvr#0G~&E|o8j)BS-k9F?Fd|JmSvxhHuvr^9#Af;nCcjpjD`T7M3R^& zUhiQtnPI-ZvS2X8qbTwHW35DVphQ8eiK=Ydy_Ebnw!@!HE4{0~_0#)##G**$vk_s& zP=q0uSCbhHRGe6QjbaB!Ttgwc6l6^Cs3KML=0=<8^7r*eHL_|bXc-Kf4mdHo#Ev>WJ#!L%VLzRU_WwZEOSYUCnFFM<2 zq*zt;XL53KlD$Nd_(=Ry@3pF`f#E+-$p4&{|Gj*}KL7wgTqO_SpBnk6cmKV1{@ML`uX~TSwJ<6+$^fx%xq3f35)?i?kFG- F0suBaB{Kj3 diff --git a/analyzer/dumps/text.dat b/analyzer/dumps/text.dat deleted file mode 100644 index 614761083b98c25dec4e60bd67cce1601a1ef2d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 512 zcmWFy^Jspf;nAC;qTtbM`c9vL!K3q|;U&i%EDQ_`FXVv4&KJxK42G9pFag=GAN^PL T5@29B0|)4QxWp)9NQ3|Yh6{U` diff --git a/analyzer/format.txt b/analyzer/format.txt new file mode 100644 index 0000000..c57ff22 --- /dev/null +++ b/analyzer/format.txt @@ -0,0 +1,7 @@ +[entry point] +[number of libraries] + 00: Import the following things. (Terminate on 00) + +[number of bytes in starting state as a uint32_t] + 00 [00-ff] : Use the following 00-ff bytes literally + [01-ff] : Repeat the next byte 02 to ff times \ No newline at end of file diff --git a/analyzer/main.py b/analyzer/main.py index d0dc095..a25fc7b 100644 --- a/analyzer/main.py +++ b/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] - if len(items) == 0: - return None - assert len(items) == 1 +@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 + + if len(items) == 1: + return items[0] + + raise ValueError(f"expected 1 or 0, got {len(items)}") + +def _single[T](ts: Generator[T]) -> T: + items = [t for t in ts] + 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, got {len(items)}") - for i in subject.sections: - print(i) - text_section = _single_or_none(i for i in subject.sections if i.Name == b".text\0\0\0") +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) - binary = { - "startingState": base64.b64encode(buffer).decode("utf8"), - "imports": [], - } + starting_state = bytes(buffer) - # find imports - # print(subject) - # print(dir(subject)) - for entry in subject.DIRECTORY_ENTRY_IMPORT: + entry_point_rva = getattr(optional_header, "AddressOfEntryPoint") + print(entry_point_rva) + entry_point = (entry_point_rva - min_address) - # 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 diff --git a/analyzer/poetry.lock b/analyzer/poetry.lock index 7d20c1f..c880e9c 100644 --- a/analyzer/poetry.lock +++ b/analyzer/poetry.lock @@ -13,5 +13,5 @@ files = [ [metadata] lock-version = "2.0" -python-versions = "^3.10" -content-hash = "6f28e4dc3bf3b09c57354693b75dc7975b70a7aac2ee7c83fc81b0058520d7f9" +python-versions = "^3.13" +content-hash = "8e680dad2071f9d7a37ca34d4fd6da67ba3922e0de45f0442c7b38d07f8fa9f0" diff --git a/analyzer/pyproject.toml b/analyzer/pyproject.toml index 9e2a8d6..d84c8ab 100644 --- a/analyzer/pyproject.toml +++ b/analyzer/pyproject.toml @@ -6,7 +6,7 @@ authors = ["Nyeogmi "] readme = "README.md" [tool.poetry.dependencies] -python = "^3.10" +python = "^3.13" pefile = "^2024.8.26" diff --git a/runner/Cargo.lock b/runner/Cargo.lock index 7c446b7..5829455 100644 --- a/runner/Cargo.lock +++ b/runner/Cargo.lock @@ -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" diff --git a/runner/Cargo.toml b/runner/Cargo.toml index 281d72a..24ae140 100644 --- a/runner/Cargo.toml +++ b/runner/Cargo.toml @@ -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] diff --git a/runner/binaries/main.dat b/runner/binaries/main.dat new file mode 100644 index 0000000000000000000000000000000000000000..18c91172a63d1c0c10301210e7cd6a73c8f3f1b1 GIT binary patch literal 20540 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 literal 0 HcmV?d00001 diff --git a/runner/binaries/main.json b/runner/binaries/main.json deleted file mode 100644 index 43bec06..0000000 --- a/runner/binaries/main.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "startingState": "VVZIg+woSI1sJCBIjTXuLwAASInxMdJBuAQAAADoHgAAALnoAwAAMdLoAgAAAOvi/yVKEAAAzMzMzMzMzMzMzP8lShAAAMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AAAAAAAAAAD//////////wAAAAAAAAAAYCAAAAAAAAAAAAAAtiAAAIAgAABwIAAAAAAAAAAAAADDIAAAkCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAgAAAAAAAAAAAAAAAAAACqIAAAAAAAAAAAAAAAAAAAoCAAAAAAAAAAAAAAAAAAAKogAAAAAAAAAAAAAAAAAAAAAFNsZWVwRXgAAABQbGF5U291bmQAS0VSTkVMMzIuZGxsAFdJTk1NLmRsbAAAAAABCwQlCwMGQgJgAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVWIEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", - "imports": [ - { - "dll": "KERNEL32.dll", - "symbol": "SleepEx", - "address": 4224 - }, - { - "dll": "WINMM.dll", - "symbol": "PlaySound", - "address": 4240 - } - ], - "entryPoint": 0 -} \ No newline at end of file diff --git a/runner/src/main.rs b/runner/src/main.rs index 0163354..6009f6f 100644 --- a/runner/src/main.rs +++ b/runner/src/main.rs @@ -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, - #[serde(with = "serde_bytes")] - symbol: Vec, - address: usize, -} - -#[serde_as] -#[derive(Debug, Deserialize)] -struct Binary { - #[serde(rename = "startingState")] - #[serde_as(as = "Base64")] - starting_state: Vec, - imports: Vec, - #[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(&mut self) -> T { + let value = core::ptr::read_unaligned(self.ptr as *const T); + self.ptr = self.ptr.byte_add(core::mem::size_of::()); + 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::(); + 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]); - // mov rcx, library name - code.write(&[0x48, 0xb9]); - code.write_ptr(library_addr); - // mov rax, LoadLibraryA - code.write(&[0x48, 0xb8]); - code.write_ptr(LOAD_LIBRARY_A); - // call rax - code.write(&[0xff, 0xd0]); + loop { + let symbol = reader.read_zt(); + if symbol.len() == 1 { + break; + } + println!("import symbol: {:?}", str::from_utf8(symbol).unwrap()); - // mov rcx, rax - code.write(&[0x48, 0x89, 0xc1]); - // mov rdx, symbol name - code.write(&[0x48, 0xba]); - code.write_ptr(symbol_addr); - // mov rax, GetProcAddress - code.write(&[0x48, 0xb8]); - code.write_ptr(GET_PROC_ADDRESS); - // call rax - code.write(&[0xff, 0xd0]); - // mov [import address], rax - code.write(&[0x48, 0xa3]); - let addr = code.address_in_binary(import.address); - code.write_ptr(addr); + let dest = reader.read::(); + let symbol_addr = strings.write(symbol); + + // mov rcx, library name + prelude.write(&[0x48, 0xb9]); + prelude.write_ptr(library_addr); + // mov rax, LoadLibraryA + prelude.write(&[0x48, 0xb8]); + prelude.write_ptr(LOAD_LIBRARY_A); + // call rax + prelude.write(&[0xff, 0xd0]); + + // mov rcx, rax + prelude.write(&[0x48, 0x89, 0xc1]); + // mov rdx, symbol name + prelude.write(&[0x48, 0xba]); + prelude.write_ptr(symbol_addr); + // mov rax, GetProcAddress + prelude.write(&[0x48, 0xb8]); + prelude.write_ptr(GET_PROC_ADDRESS); + // call rax + prelude.write(&[0xff, 0xd0]); + // mov [import address], rax + 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::() 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 = vec![]; let _ = input.read_to_end(&mut buf).unwrap(); - let binary = serde_json::from_slice::(&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::() 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 { } return None; } -/* -unsafe fn _main_local() { - let mut input = File::open("binaries/main.json").unwrap(); - let mut buf: Vec = vec![]; - let _ = input.read_to_end(&mut buf).unwrap(); - - let binary = serde_json::from_slice::(&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(); -} - -*/