diff options
| author | itsme <itsme@xs4all.nl> | 2021-07-06 19:26:42 +0200 |
|---|---|---|
| committer | itsme <itsme@xs4all.nl> | 2021-07-06 19:26:42 +0200 |
| commit | a9886b9d52c3bce0a4b58805b5597efccc55225a (patch) | |
| tree | 4133e30e57109385ade3f756970058fe1edac255 | |
initial commit
| -rw-r--r-- | README.md | 19 | ||||
| -rw-r--r-- | crodump.py | 160 | ||||
| -rw-r--r-- | docs/exe-packer-notes.txt | 436 | ||||
| -rw-r--r-- | hexdump.py | 27 | ||||
| -rw-r--r-- | koddecoder.py | 32 |
5 files changed, 674 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..6119860 --- /dev/null +++ b/README.md | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | # crodump | ||
| 2 | |||
| 3 | `crodump.py` is a script which can analyse cronos databases. | ||
| 4 | |||
| 5 | There is the `kodump` option, which does low level deobfuscation at arbitrary offsets, | ||
| 6 | optionally deobfuscating with all possible `shift` values. | ||
| 7 | |||
| 8 | Then the `crodump` option which reads .tad + .dat file pairs, and prints the records found. | ||
| 9 | |||
| 10 | |||
| 11 | ## supporting modules | ||
| 12 | |||
| 13 | * hexdump.py | ||
| 14 | * koddecoder.py | ||
| 15 | |||
| 16 | # packer notes | ||
| 17 | |||
| 18 | see docs/exe-packer-notes.txt, notes on the binary packer used by Cronos.exe | ||
| 19 | |||
diff --git a/crodump.py b/crodump.py new file mode 100644 index 0000000..a2a94a1 --- /dev/null +++ b/crodump.py | |||
| @@ -0,0 +1,160 @@ | |||
| 1 | import os.path | ||
| 2 | import struct | ||
| 3 | from binascii import b2a_hex | ||
| 4 | from hexdump import hexdump, asasc, tohex | ||
| 5 | from koddecoder import kodecode | ||
| 6 | """ | ||
| 7 | python3 crodump.py crodump chechnya_proverki_ul_2012 | ||
| 8 | python3 crodump.py kodump -s 6 -o 0x4cc9 -e 0x5d95 chechnya_proverki_ul_2012/CroStru.dat | ||
| 9 | """ | ||
| 10 | |||
| 11 | class Datafile: | ||
| 12 | def __init__(self, dat, tad): | ||
| 13 | self.dat = dat | ||
| 14 | self.tad = tad | ||
| 15 | |||
| 16 | self.readtad() | ||
| 17 | |||
| 18 | def readtad(self): | ||
| 19 | self.tad.seek(0) | ||
| 20 | hdrdata = self.tad.read(2*4) | ||
| 21 | self.tadhdr = struct.unpack("<2L", hdrdata) | ||
| 22 | indexdata = self.tad.read() | ||
| 23 | self.tadidx = [ struct.unpack_from("<3L", indexdata, 12*_) for _ in range(len(indexdata)//12) ] | ||
| 24 | |||
| 25 | def readdata(self, ofs, size): | ||
| 26 | self.dat.seek(ofs) | ||
| 27 | return self.dat.read(size) | ||
| 28 | |||
| 29 | def dump(self, args, dokodecode=False, plainbytes=0): | ||
| 30 | print("tadhdr: %08x %08x" % tuple(self.tadhdr)) | ||
| 31 | for i, (ofs, ln, chk) in enumerate(self.tadidx): | ||
| 32 | if ln==0xFFFFFFFF: | ||
| 33 | print("%5d: %08x %08x %08x" % (i, ofs, ln, chk)) | ||
| 34 | continue | ||
| 35 | flags = ln>>24 | ||
| 36 | ln &= 0xFFFFFFF | ||
| 37 | dat = self.readdata(ofs, ln) | ||
| 38 | plain = b'' | ||
| 39 | if dokodecode and not args.nokod: | ||
| 40 | plain = dat[:plainbytes] | ||
| 41 | dat = kodecode(i+1, dat[plainbytes:]) | ||
| 42 | if args.ascdump: | ||
| 43 | print("%5d: %08x-%08x: (%02x:%08x) %s %s" % (i, ofs, ofs+ln, flags, chk, tohex(plain), asasc(dat))) | ||
| 44 | else: | ||
| 45 | print("%5d: %08x-%08x: (%02x:%08x) %s %s" % (i, ofs, ofs+ln, flags, chk, tohex(plain), tohex(dat))) | ||
| 46 | |||
| 47 | class Database: | ||
| 48 | def __init__(self, dbdir): | ||
| 49 | self.dbdir = dbdir | ||
| 50 | |||
| 51 | self.stru = self.getfile("Stru") | ||
| 52 | self.index = self.getfile("Index") | ||
| 53 | self.bank = self.getfile("Bank") | ||
| 54 | self.sys = self.getfile("Sys") | ||
| 55 | |||
| 56 | def getfile(self, name): | ||
| 57 | try: | ||
| 58 | return Datafile(open(self.getname(name, "dat"), "rb"), open(self.getname(name, "tad"), "rb")) | ||
| 59 | except IOError: | ||
| 60 | return | ||
| 61 | |||
| 62 | def getname(self, name, ext): | ||
| 63 | return os.path.join(self.dbdir, "Cro%s.%s" % (name, ext)) | ||
| 64 | |||
| 65 | |||
| 66 | def decode_kod(args, data): | ||
| 67 | """ | ||
| 68 | various methods of hexdumping KOD decoded data. | ||
| 69 | """ | ||
| 70 | if args.nokod: | ||
| 71 | # plain hexdump, no KOD decode | ||
| 72 | hexdump(args.offset, data) | ||
| 73 | elif args.shift: | ||
| 74 | # explicitly specified shift. | ||
| 75 | args.shift = int(args.shift, 0) | ||
| 76 | enc = kodecode(args.shift, data) | ||
| 77 | hexdump(args.offset, enc) | ||
| 78 | else: | ||
| 79 | # output with all possible 'shift' values. | ||
| 80 | for s in range(256): | ||
| 81 | enc = kodecode(s, data) | ||
| 82 | if args.ascdump: | ||
| 83 | print("%02x: %s" % (s, asasc(enc))) | ||
| 84 | else: | ||
| 85 | print("%02x: %s" % (s, tohex(enc))) | ||
| 86 | |||
| 87 | |||
| 88 | |||
| 89 | def kod_hexdump(args): | ||
| 90 | """ | ||
| 91 | KOD decode a section of a data file | ||
| 92 | """ | ||
| 93 | args.offset = int(args.offset, 0) | ||
| 94 | if args.length: | ||
| 95 | args.length = int(args.length, 0) | ||
| 96 | elif args.endofs: | ||
| 97 | args.endofs = int(args.endofs, 0) | ||
| 98 | args.length = args.endofs - args.offset | ||
| 99 | |||
| 100 | if args.filename: | ||
| 101 | with open(args.filename, "rb") as fh: | ||
| 102 | fh.seek(args.offset) | ||
| 103 | data = fh.read(args.length) | ||
| 104 | decode_kod(args, data) | ||
| 105 | else: | ||
| 106 | # no filename -> read from stdin. | ||
| 107 | import sys | ||
| 108 | data = sys.stdin.buffer.read() | ||
| 109 | decode_kod(args, data) | ||
| 110 | |||
| 111 | |||
| 112 | def cro_dump(args): | ||
| 113 | db = Database(args.dbdir) | ||
| 114 | |||
| 115 | if db.stru: | ||
| 116 | print("stru") | ||
| 117 | db.stru.dump(args, dokodecode=True) | ||
| 118 | if db.index: | ||
| 119 | print("index") | ||
| 120 | db.index.dump(args) | ||
| 121 | if db.bank: | ||
| 122 | print("bank") | ||
| 123 | db.bank.dump(args) | ||
| 124 | if db.sys: | ||
| 125 | print("sys") | ||
| 126 | db.sys.dump(args, dokodecode=True, plainbytes=8) | ||
| 127 | |||
| 128 | |||
| 129 | def main(): | ||
| 130 | import argparse | ||
| 131 | parser = argparse.ArgumentParser(description='CRO hexdumper') | ||
| 132 | subparsers = parser.add_subparsers() | ||
| 133 | parser.set_defaults(handler=None) | ||
| 134 | |||
| 135 | ko = subparsers.add_parser('kodump', help='KOD dumper') | ||
| 136 | ko.add_argument('--offset', '-o', type=str, default="0") | ||
| 137 | ko.add_argument('--length', '-l', type=str) | ||
| 138 | ko.add_argument('--endofs', '-e', type=str) | ||
| 139 | ko.add_argument('--shift', '-s', type=str) | ||
| 140 | ko.add_argument('--ascdump', '-a', action='store_true') | ||
| 141 | ko.add_argument('--nokod', '-n', action='store_true') | ||
| 142 | ko.add_argument('filename', type=str, nargs='?') | ||
| 143 | ko.set_defaults(handler=kod_hexdump) | ||
| 144 | |||
| 145 | cro = subparsers.add_parser('crodump', help='CROdumper') | ||
| 146 | cro.add_argument('--kodecode', '-k', action='store_true') | ||
| 147 | cro.add_argument('--ascdump', '-a', action='store_true') | ||
| 148 | cro.add_argument('--nokod', '-n', action='store_true') | ||
| 149 | cro.add_argument('dbdir', type=str) | ||
| 150 | cro.set_defaults(handler=cro_dump) | ||
| 151 | |||
| 152 | args = parser.parse_args() | ||
| 153 | |||
| 154 | if args.handler: | ||
| 155 | args.handler(args) | ||
| 156 | |||
| 157 | |||
| 158 | if __name__=='__main__': | ||
| 159 | main() | ||
| 160 | |||
diff --git a/docs/exe-packer-notes.txt b/docs/exe-packer-notes.txt new file mode 100644 index 0000000..d1a33a0 --- /dev/null +++ b/docs/exe-packer-notes.txt | |||
| @@ -0,0 +1,436 @@ | |||
| 1 | 37491b1b85fdf3969c45e83aa2d205ed = md5(plus/Cronos.exe) | ||
| 2 | |||
| 3 | dump -o 0x314f7b -4 -l 0x810 plus/Cronos.exe | ||
| 4 | |||
| 5 | 0x100000000-0x1947A71E = 0xE6B858E2 | ||
| 6 | |||
| 7 | add 4C27824Bh | ||
| 8 | sub 47878428h | ||
| 9 | sub 1DE7A541h | ||
| 10 | |||
| 11 | |||
| 12 | seg000:00401000 start proc near | ||
| 13 | seg000:00401000 push offset loc_F82001 | ||
| 14 | seg000:00401005 call nullsub_1 | ||
| 15 | seg000:0040100A retn | ||
| 16 | seg000:0040100B nullsub_1: | ||
| 17 | seg000:0040100B retn | ||
| 18 | |||
| 19 | .data:00F82001 | ||
| 20 | .data:00F82001 loc_F82001: ; DATA XREF: start↑o | ||
| 21 | .data:00F82001 60 pusha | ||
| 22 | .data:00F82002 E8 03 00 00 00 call loc_F8200A | ||
| 23 | |||
| 24 | .data:00F82008 EB 04 jmp short loc_F8200E | ||
| 25 | .data:00F8200A | ||
| 26 | .data:00F8200A loc_F8200A: ; CODE XREF: .data:00F82002↑j | ||
| 27 | .data:00F8200A 5D pop ebp | ||
| 28 | .data:00F8200B 45 inc ebp | ||
| 29 | .data:00F8200C 55 push ebp ; skips '0xE9' at 00F82007 | ||
| 30 | .data:00F8200D C3 retn | ||
| 31 | .data:00F8200E | ||
| 32 | .data:00F8200E loc_F8200E: ; CODE XREF: .data:00F82008↑j | ||
| 33 | .data:00F8200E E8 01 00 00 00 call loc_F82014 | ||
| 34 | |||
| 35 | .data:00F82014 | ||
| 36 | .data:00F82014 loc_F82014: ; CODE XREF: .data:loc_F8200E↑j | ||
| 37 | .data:00F82014 5D pop ebp | ||
| 38 | .data:00F82015 BB ED FF FF FF mov ebx, -13h | ||
| 39 | .data:00F8201A 03 DD add ebx, ebp ; -> ebx = 0xf82000 | ||
| 40 | .data:00F8201C 81 EB 00 20 B8 00 sub ebx, 0B82000h ; -> 0x400000 | ||
| 41 | .data:00F82022 80 7D 4D 01 cmp ss:(byte_F82060 - 0F82013h)[ebp], 1 | ||
| 42 | .data:00F82026 75 0C jnz short loc_F82034 | ||
| 43 | .data:00F82028 8B 74 24 28 mov esi, [esp+28h] | ||
| 44 | .data:00F8202C 83 FE 01 cmp esi, 1 | ||
| 45 | .data:00F8202F 89 5D 4E mov ss:(dword_F82061 - 0F82013h)[ebp], ebx | ||
| 46 | .data:00F82032 75 31 jnz short loc_F82065 | ||
| 47 | .data:00F82034 | ||
| 48 | .data:00F82034 loc_F82034: ; CODE XREF: .data:00F82026↑j | ||
| 49 | .data:00F82034 8D 45 53 lea eax, (loc_F82065+1 - 0F82013h)[ebp] | ||
| 50 | .data:00F82037 50 push eax | ||
| 51 | .data:00F82038 53 push ebx | ||
| 52 | .data:00F82039 FF B5 E9 09 00 00 push ss:(GetModuleHandleA - 0F82013h)[ebp] | ||
| 53 | .data:00F8203F 8D 45 35 lea eax, (dword_F82048 - 0F82013h)[ebp] | ||
| 54 | .data:00F82042 50 push eax | ||
| 55 | .data:00F82043 E9 82 00 00 00 jmp loc_F820CA | ||
| 56 | |||
| 57 | .data:00F820CA | ||
| 58 | .data:00F820CA loc_F820CA: ; CODE XREF: .data:00F82043↑j | ||
| 59 | .data:00F820CA 66 8B F8 mov di, ax ; ----- ignore | ||
| 60 | .data:00F820CD E8 13 00 00 00 call loc_F820E5 | ||
| 61 | |||
| 62 | .data:00F820E5 | ||
| 63 | .data:00F820E5 loc_F820E5: ; CODE XREF: .data:00F820CD↑p | ||
| 64 | .data:00F820E5 E9 0D 00 00 00 jmp loc_F820F7 | ||
| 65 | |||
| 66 | .data:00F820F7 | ||
| 67 | .data:00F820F7 loc_F820F7: ; CODE XREF: .data:loc_F820E5↑j | ||
| 68 | .data:00F820F7 59 pop ecx ; -> 00F820D2 | ||
| 69 | .data:00F820F8 66 8B D6 mov dx, si ; ----------- ignore | ||
| 70 | .data:00F820FB | ||
| 71 | .data:00F820FB loc_F820FB: ; CODE XREF: .data:00F8211A↓j | ||
| 72 | .data:00F820FB 81 C1 AF 08 00 00 add ecx, 8AFh ; -> 00F82981 | ||
| 73 | .data:00F82101 68 FF 01 00 00 push 1FFh | ||
| 74 | .data:00F82106 58 pop eax | ||
| 75 | .data:00F82107 E8 14 00 00 00 call loc_F82120 ; ecx = ptr = caller+0x8af, eax = size = 0x1ff | ||
| 76 | .data:00F82107 ; | ||
| 77 | .data:00F82107 ; caller = 00F820D2 -> data is at 00F82981 | ||
| 78 | .data:00F82107 ; | ||
| 79 | .data:00F82107 ; 00F82185-00F82981 file: 00315781 | ||
| 80 | |||
| 81 | |||
| 82 | .data:00F82120 | ||
| 83 | .data:00F82120 loc_F82120: ; CODE XREF: .data:00F82107↑p | ||
| 84 | .data:00F82120 5A pop edx ; -> 00F8210C | ||
| 85 | .data:00F82121 | ||
| 86 | .data:00F82121 loc_F82121: ; CODE XREF: .data:loc_F82176↓j | ||
| 87 | .data:00F82121 8B 19 mov ebx, [ecx] | ||
| 88 | .data:00F82123 0F BF F1 movsx esi, cx ; ----- ignore | ||
| 89 | .data:00F82126 81 C3 4B 82 27 4C add ebx, 4C27824Bh | ||
| 90 | .data:00F8212C 81 EB 28 84 87 47 sub ebx, 47878428h | ||
| 91 | .data:00F82132 0F B7 D2 movzx edx, dx ; ----- ignore | ||
| 92 | .data:00F82135 81 EB 41 A5 E7 1D sub ebx, 1DE7A541h ; -0x627F3C40 | ||
| 93 | .data:00F8213B 66 81 E2 D5 9C and dx, 9CD5h ; ----- ignore | ||
| 94 | .data:00F82140 89 19 mov [ecx], ebx | ||
| 95 | .data:00F82142 80 D2 B7 adc dl, 0B7h ; '·' ; ----- ignore | ||
| 96 | .data:00F82145 81 E9 8D 91 24 67 sub ecx, 6724918Dh | ||
| 97 | .data:00F8214B 66 8B F1 mov si, cx ; ----- ignore | ||
| 98 | .data:00F8214E 81 C1 89 91 24 67 add ecx, 67249189h ; -4 | ||
| 99 | .data:00F82154 0F BF F8 movsx edi, ax ; ----- ignore | ||
| 100 | .data:00F82157 83 E8 01 sub eax, 1 | ||
| 101 | .data:00F8215A 0F 85 0E 00 00 00 jnz loc_F8216E | ||
| 102 | .data:00F82160 8B D0 mov edx, eax | ||
| 103 | .data:00F82162 E9 22 00 00 00 jmp near ptr unk_F82189 | ||
| 104 | |||
| 105 | .data:00F8216E | ||
| 106 | .data:00F8216E loc_F8216E: ; CODE XREF: .data:00F8215A↑j | ||
| 107 | .data:00F8216E 0F 80 02 00 00 00 jo loc_F82176 | ||
| 108 | .data:00F82174 53 push ebx | ||
| 109 | .data:00F82175 5E pop esi | ||
| 110 | .data:00F82176 | ||
| 111 | .data:00F82176 loc_F82176: ; CODE XREF: .data:loc_F8216E↑j | ||
| 112 | .data:00F82176 E9 A6 FF FF FF jmp loc_F82121 | ||
| 113 | |||
| 114 | |||
| 115 | .data:00F82048 00 00 00 00 dword_F82048 dd 0 ; DATA XREF: .data:00F8203F↑o | ||
| 116 | .data:00F82048 ; .data:00F8209B↓r ... | ||
| 117 | .data:00F8204C 00 00 00 00 dd 0 | ||
| 118 | .data:00F82050 00 00 00 00 dword_F82050 dd 0 ; DATA XREF: .data:00F820B1↓r | ||
| 119 | .data:00F82054 00 00 00 00 dword_F82054 dd 0 ; DATA XREF: .data:00F82092↓r | ||
| 120 | .data:00F82058 00 00 00 00 dd 0 | ||
| 121 | .data:00F8205C 00 00 00 00 dd 0 | ||
| 122 | .data:00F82060 00 byte_F82060 db 0 ; DATA XREF: .data:00F82022↑r | ||
| 123 | .data:00F82061 00 00 00 00 dword_F82061 dd 0 ; DATA XREF: .data:00F8202F↑w | ||
| 124 | .data:00F82061 ; .data:00F8206C↓r ... | ||
| 125 | .data:00F82065 | ||
| 126 | .data:00F82065 loc_F82065: ; CODE XREF: .data:00F82032↑j | ||
| 127 | .data:00F82065 ; DATA XREF: .data:loc_F82034↑o | ||
| 128 | .data:00F82065 B8 F8 C0 A5 23 mov eax, 23A5C0F8h | ||
| 129 | .data:00F8206A 50 push eax | ||
| 130 | .data:00F8206B 50 push eax | ||
| 131 | .data:00F8206C 03 45 4E add eax, ss:(dword_F82061 - 0F82013h)[ebp] | ||
| 132 | .data:00F8206F 5B pop ebx | ||
| 133 | .data:00F82070 85 C0 test eax, eax | ||
| 134 | .data:00F82072 74 1C jz short loc_F82090 | ||
| 135 | .data:00F82074 EB 01 jmp short loc_F82077 | ||
| 136 | |||
| 137 | .data:00F82077 | ||
| 138 | .data:00F82077 loc_F82077: ; CODE XREF: .data:00F82074↑j | ||
| 139 | .data:00F82077 81 FB F8 C0 A5 23 cmp ebx, 23A5C0F8h | ||
| 140 | .data:00F8207D 74 35 jz short loc_F820B4 | ||
| 141 | .data:00F8207F 33 D2 xor edx, edx | ||
| 142 | .data:00F82081 56 push esi | ||
| 143 | .data:00F82082 6A 00 push 0 | ||
| 144 | .data:00F82084 56 push esi | ||
| 145 | .data:00F82085 FF 75 4E push ss:(dword_F82061 - 0F82013h)[ebp] | ||
| 146 | .data:00F82088 FF D0 call eax | ||
| 147 | .data:00F8208A 5E pop esi | ||
| 148 | .data:00F8208B 83 FE 00 cmp esi, 0 | ||
| 149 | .data:00F8208E 75 24 jnz short loc_F820B4 | ||
| 150 | .data:00F82090 | ||
| 151 | .data:00F82090 loc_F82090: ; CODE XREF: .data:00F82072↑j | ||
| 152 | .data:00F82090 33 D2 xor edx, edx | ||
| 153 | .data:00F82092 8B 45 41 mov eax, ss:(dword_F82054 - 0F82013h)[ebp] | ||
| 154 | .data:00F82095 85 C0 test eax, eax | ||
| 155 | .data:00F82097 74 07 jz short loc_F820A0 | ||
| 156 | .data:00F82099 52 push edx | ||
| 157 | .data:00F8209A 52 push edx | ||
| 158 | .data:00F8209B FF 75 35 push ss:(dword_F82048 - 0F82013h)[ebp] | ||
| 159 | .data:00F8209E FF D0 call eax | ||
| 160 | .data:00F820A0 | ||
| 161 | .data:00F820A0 loc_F820A0: ; CODE XREF: .data:00F82097↑j | ||
| 162 | .data:00F820A0 8B 45 35 mov eax, ss:(dword_F82048 - 0F82013h)[ebp] | ||
| 163 | .data:00F820A3 85 C0 test eax, eax | ||
| 164 | .data:00F820A5 74 0D jz short loc_F820B4 | ||
| 165 | .data:00F820A7 68 00 80 00 00 push 8000h | ||
| 166 | .data:00F820AC 6A 00 push 0 | ||
| 167 | .data:00F820AE FF 75 35 push ss:(dword_F82048 - 0F82013h)[ebp] | ||
| 168 | .data:00F820B1 FF 55 3D call ss:(dword_F82050 - 0F82013h)[ebp] | ||
| 169 | .data:00F820B4 | ||
| 170 | .data:00F820B4 loc_F820B4: ; CODE XREF: .data:00F8207D↑j | ||
| 171 | .data:00F820B4 ; .data:00F8208E↑j ... | ||
| 172 | .data:00F820B4 5B pop ebx | ||
| 173 | .data:00F820B5 0B DB or ebx, ebx | ||
| 174 | .data:00F820B7 61 popa | ||
| 175 | .data:00F820B8 75 06 jnz short loc_F820C0 | ||
| 176 | .data:00F820BA 6A 01 push 1 | ||
| 177 | .data:00F820BC 58 pop eax | ||
| 178 | .data:00F820BD C2 0C 00 retn 0Ch | ||
| 179 | .data:00F820C0 | ||
| 180 | .data:00F820C0 loc_F820C0: ; CODE XREF: .data:00F820B8↑j | ||
| 181 | .data:00F820C0 33 C0 xor eax, eax | ||
| 182 | .data:00F820C2 F7 D8 neg eax | ||
| 183 | .data:00F820C4 1B C0 sbb eax, eax | ||
| 184 | .data:00F820C6 40 inc eax | ||
| 185 | .data:00F820C7 C2 0C 00 retn 0Ch | ||
| 186 | |||
| 187 | |||
| 188 | |||
| 189 | |||
| 190 | .data:00F82007 E9 db 0E9h ; é | ||
| 191 | |||
| 192 | .data:00F82013 EB db 0EBh ; ë | ||
| 193 | |||
| 194 | .data:00F82076 E8 db 0E8h ; è | ||
| 195 | |||
| 196 | |||
| 197 | .data:00F820D2 1F db 1Fh | ||
| 198 | .data:00F820D3 6C db 6Ch ; l | ||
| 199 | .data:00F820D4 35 db 35h ; 5 | ||
| 200 | .data:00F820D5 CA db 0CAh ; Ê | ||
| 201 | .data:00F820D6 3B db 3Bh ; ; | ||
| 202 | .data:00F820D7 58 db 58h ; X | ||
| 203 | .data:00F820D8 B1 db 0B1h ; ± | ||
| 204 | .data:00F820D9 96 db 96h ; – | ||
| 205 | .data:00F820DA 17 db 17h | ||
| 206 | .data:00F820DB 04 db 4 | ||
| 207 | .data:00F820DC ED db 0EDh ; í | ||
| 208 | .data:00F820DD 22 db 22h ; " | ||
| 209 | .data:00F820DE B3 db 0B3h ; ³ | ||
| 210 | .data:00F820DF 70 db 70h ; p | ||
| 211 | .data:00F820E0 E9 db 0E9h ; é | ||
| 212 | .data:00F820E1 6E db 6Eh ; n | ||
| 213 | .data:00F820E2 0F db 0Fh | ||
| 214 | .data:00F820E3 9C db 9Ch ; œ | ||
| 215 | .data:00F820E4 A5 db 0A5h ; ¥ | ||
| 216 | |||
| 217 | |||
| 218 | |||
| 219 | .data:00F820EA 21 db 21h ; ! | ||
| 220 | .data:00F820EB 46 db 46h ; F | ||
| 221 | .data:00F820EC 07 db 7 | ||
| 222 | .data:00F820ED 34 db 34h ; 4 | ||
| 223 | .data:00F820EE 5D db 5Dh ; ] | ||
| 224 | .data:00F820EF D2 db 0D2h ; Ò | ||
| 225 | .data:00F820F0 A3 db 0A3h ; £ | ||
| 226 | .data:00F820F1 A0 db 0A0h ; | ||
| 227 | .data:00F820F2 59 db 59h ; Y | ||
| 228 | .data:00F820F3 1E db 1Eh | ||
| 229 | .data:00F820F4 FF db 0FFh ; ÿ | ||
| 230 | .data:00F820F5 CC db 0CCh ; Ì | ||
| 231 | .data:00F820F6 15 db 15h | ||
| 232 | |||
| 233 | |||
| 234 | .data:00F8210C FC db 0FCh ; ü | ||
| 235 | .data:00F8210D 85 db 85h ; … | ||
| 236 | .data:00F8210E DA db 0DAh ; Ú | ||
| 237 | .data:00F8210F 0B db 0Bh | ||
| 238 | .data:00F82110 E8 db 0E8h ; è | ||
| 239 | .data:00F82111 01 db 1 | ||
| 240 | .data:00F82112 A6 db 0A6h ; ¦ | ||
| 241 | .data:00F82113 E7 db 0E7h ; ç | ||
| 242 | .data:00F82114 94 db 94h ; ” | ||
| 243 | .data:00F82115 3D db 3Dh ; = | ||
| 244 | .data:00F82116 32 db 32h ; 2 | ||
| 245 | .data:00F82117 83 db 83h ; ƒ | ||
| 246 | .data:00F82118 00 db 0 | ||
| 247 | .data:00F82119 39 db 39h ; 9 | ||
| 248 | .data:00F8211A 7E db 7Eh ; ~ | ||
| 249 | .data:00F8211B DF db 0DFh ; ß | ||
| 250 | .data:00F8211C 2C db 2Ch ; , | ||
| 251 | .data:00F8211D F5 db 0F5h ; õ | ||
| 252 | .data:00F8211E 8A db 8Ah ; Š | ||
| 253 | .data:00F8211F FB db 0FBh ; û | ||
| 254 | |||
| 255 | |||
| 256 | |||
| 257 | .data:00F82167 43 db 43h ; C | ||
| 258 | .data:00F82168 C0 db 0C0h ; À | ||
| 259 | .data:00F82169 F9 db 0F9h ; ù | ||
| 260 | .data:00F8216A 3E db 3Eh ; > | ||
| 261 | .data:00F8216B 9F db 9Fh ; Ÿ | ||
| 262 | .data:00F8216C EC db 0ECh ; ì | ||
| 263 | .data:00F8216D B5 db 0B5h ; µ | ||
| 264 | |||
| 265 | .data:00F8217B EE db 0EEh ; î | ||
| 266 | .data:00F8217C 8F db 8Fh | ||
| 267 | .data:00F8217D 1C db 1Ch | ||
| 268 | .data:00F8217E 25 db 25h ; % | ||
| 269 | .data:00F8217F FA db 0FAh ; ú | ||
| 270 | .data:00F82180 AB db 0ABh ; « | ||
| 271 | .data:00F82181 08 db 8 | ||
| 272 | .data:00F82182 A1 db 0A1h ; ¡ | ||
| 273 | .data:00F82183 C6 db 0C6h ; Æ | ||
| 274 | .data:00F82184 87 db 87h ; ‡ | ||
| 275 | .data:00F82185 B4 db 0B4h ; ´ | ||
| 276 | .data:00F82186 DD db 0DDh ; Ý | ||
| 277 | .data:00F82187 52 db 52h ; R | ||
| 278 | .data:00F82188 23 db 23h ; # | ||
| 279 | .data:00F82189 84 unk_F82189 db 84h ; „ ; CODE XREF: .data:00F82162↑j | ||
| 280 | .data:00F8218A 28 db 28h ; ( | ||
| 281 | |||
| 282 | |||
| 283 | |||
| 284 | |||
| 285 | ---------------- | ||
| 286 | wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow); | ||
| 287 | |||
| 288 | [esp+2c] arg: pCmdLine | ||
| 289 | [esp+28] arg: nCmdShow | ||
| 290 | [esp+24] caller address | ||
| 291 | [esp+20] EAX | ||
| 292 | [esp+1c] ECX | ||
| 293 | [esp+18] EDX | ||
| 294 | [esp+14] EBX | ||
| 295 | [esp+10] ESP == esp+20 | ||
| 296 | [esp+c] EBP | ||
| 297 | [esp+8] ESI | ||
| 298 | [esp+4] EDI | ||
| 299 | [esp] | ||
| 300 | |||
| 301 | |||
| 302 | loc_F82001: ; DATA XREF: start↑o | ||
| 303 | pusha | ||
| 304 | call loc_F82014 | ||
| 305 | loc_F82014: ; CODE XREF: .data:loc_F8200E↑j | ||
| 306 | pop ebp | ||
| 307 | mov ebx, -13h | ||
| 308 | add ebx, ebp ; -> ebx = 0xf82000 | ||
| 309 | sub ebx, 0B82000h ; -> 0x400000 | ||
| 310 | cmp ss:(byte_F82060 - 0F82013h)[ebp], 1 | ||
| 311 | jnz short loc_F82034 | ||
| 312 | mov esi, [esp+28h] | ||
| 313 | cmp esi, 1 | ||
| 314 | mov ss:(dword_F82061 - 0F82013h)[ebp], ebx | ||
| 315 | jnz short loc_F82065 | ||
| 316 | |||
| 317 | loc_F82034: ; CODE XREF: .data:00F82026↑j | ||
| 318 | lea eax, (loc_F82065+1 - 0F82013h)[ebp] | ||
| 319 | push eax | ||
| 320 | push ebx | ||
| 321 | push ss:(GetModuleHandleA - 0F82013h)[ebp] | ||
| 322 | lea eax, (dword_F82048 - 0F82013h)[ebp] | ||
| 323 | push eax | ||
| 324 | |||
| 325 | lea ecx, 00F820D2h | ||
| 326 | add ecx, 8AFh ; -> 00F82981 | ||
| 327 | push 1FFh | ||
| 328 | pop eax | ||
| 329 | ; ecx = ptr = caller+0x8af, eax = size = 0x1ff | ||
| 330 | ; | ||
| 331 | ; caller = 00F820D2 -> data is at 00F82981 | ||
| 332 | ; | ||
| 333 | ; 00F82185-00F82981 file: 00315781 | ||
| 334 | |||
| 335 | lea edx, 00F8210Ch | ||
| 336 | |||
| 337 | loc_F82121: ; CODE XREF: .data:loc_F82176↓j | ||
| 338 | mov ebx, [ecx] | ||
| 339 | add ebx, 4C27824Bh | ||
| 340 | sub ebx, 47878428h | ||
| 341 | sub ebx, 1DE7A541h ; -0x627F3C40 | ||
| 342 | mov [ecx], ebx | ||
| 343 | sub ecx, 6724918Dh | ||
| 344 | add ecx, 67249189h ; -4 | ||
| 345 | sub eax, 1 | ||
| 346 | jnz loc_F8216E | ||
| 347 | mov edx, eax | ||
| 348 | jmp near ptr unk_F82189 | ||
| 349 | |||
| 350 | |||
| 351 | loc_F8216E: ; CODE XREF: .data:00F8215A↑j | ||
| 352 | jo loc_F82176 | ||
| 353 | push ebx | ||
| 354 | pop esi | ||
| 355 | |||
| 356 | loc_F82176: ; CODE XREF: .data:loc_F8216E↑j | ||
| 357 | jmp loc_F82121 | ||
| 358 | |||
| 359 | |||
| 360 | |||
| 361 | |||
| 362 | dword_F82048 dd 0 ; DATA XREF: .data:00F8203F↑o | ||
| 363 | ; .data:00F8209B↓r ... | ||
| 364 | dd 0 | ||
| 365 | dword_F82050 dd 0 ; DATA XREF: .data:00F820B1↓r | ||
| 366 | dword_F82054 dd 0 ; DATA XREF: .data:00F82092↓r | ||
| 367 | dd 0 | ||
| 368 | dd 0 | ||
| 369 | byte_F82060 db 0 ; DATA XREF: .data:00F82022↑r | ||
| 370 | dword_F82061 dd 0 ; DATA XREF: .data:00F8202F↑w | ||
| 371 | ; .data:00F8206C↓r ... | ||
| 372 | |||
| 373 | loc_F82065: ; CODE XREF: .data:00F82032↑j | ||
| 374 | ; DATA XREF: .data:loc_F82034↑o | ||
| 375 | mov eax, 23A5C0F8h | ||
| 376 | push eax | ||
| 377 | push eax | ||
| 378 | add eax, ss:(dword_F82061 - 0F82013h)[ebp] | ||
| 379 | pop ebx | ||
| 380 | test eax, eax | ||
| 381 | jz short loc_F82090 | ||
| 382 | jmp short loc_F82077 | ||
| 383 | |||
| 384 | |||
| 385 | loc_F82077: ; CODE XREF: .data:00F82074↑j | ||
| 386 | cmp ebx, 23A5C0F8h | ||
| 387 | jz short loc_F820B4 | ||
| 388 | xor edx, edx | ||
| 389 | push esi | ||
| 390 | push 0 | ||
| 391 | push esi | ||
| 392 | push ss:(dword_F82061 - 0F82013h)[ebp] | ||
| 393 | call eax | ||
| 394 | pop esi | ||
| 395 | cmp esi, 0 | ||
| 396 | jnz short loc_F820B4 | ||
| 397 | |||
| 398 | loc_F82090: ; CODE XREF: .data:00F82072↑j | ||
| 399 | xor edx, edx | ||
| 400 | mov eax, ss:(dword_F82054 - 0F82013h)[ebp] | ||
| 401 | test eax, eax | ||
| 402 | jz short loc_F820A0 | ||
| 403 | push edx | ||
| 404 | push edx | ||
| 405 | push ss:(dword_F82048 - 0F82013h)[ebp] | ||
| 406 | call eax | ||
| 407 | |||
| 408 | loc_F820A0: ; CODE XREF: .data:00F82097↑j | ||
| 409 | mov eax, ss:(dword_F82048 - 0F82013h)[ebp] | ||
| 410 | test eax, eax | ||
| 411 | jz short loc_F820B4 | ||
| 412 | push 8000h | ||
| 413 | push 0 | ||
| 414 | push ss:(dword_F82048 - 0F82013h)[ebp] | ||
| 415 | call ss:(dword_F82050 - 0F82013h)[ebp] | ||
| 416 | |||
| 417 | loc_F820B4: ; CODE XREF: .data:00F8207D↑j | ||
| 418 | ; .data:00F8208E↑j ... | ||
| 419 | pop ebx | ||
| 420 | or ebx, ebx | ||
| 421 | popa | ||
| 422 | jnz short loc_F820C0 | ||
| 423 | push 1 | ||
| 424 | pop eax | ||
| 425 | retn 0Ch | ||
| 426 | |||
| 427 | loc_F820C0: ; CODE XREF: .data:00F820B8↑j | ||
| 428 | xor eax, eax | ||
| 429 | neg eax | ||
| 430 | sbb eax, eax | ||
| 431 | inc eax | ||
| 432 | retn 0Ch | ||
| 433 | |||
| 434 | |||
| 435 | |||
| 436 | |||
diff --git a/hexdump.py b/hexdump.py new file mode 100644 index 0000000..c119b16 --- /dev/null +++ b/hexdump.py | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | import struct | ||
| 2 | from binascii import b2a_hex | ||
| 3 | """ | ||
| 4 | Simple hexdump, 16 bytes per line with offset. | ||
| 5 | """ | ||
| 6 | |||
| 7 | def ashex(line): | ||
| 8 | return " ".join("%02x" % _ for _ in line) | ||
| 9 | def aschr(b): | ||
| 10 | if 32<=b<0x7f: | ||
| 11 | return "%c" % b | ||
| 12 | elif 0x80<=b<=0xff: | ||
| 13 | try: | ||
| 14 | c = struct.pack("<B", b).decode('cp1251') | ||
| 15 | if c: | ||
| 16 | return c | ||
| 17 | except: | ||
| 18 | pass | ||
| 19 | return "." | ||
| 20 | def asasc(line): | ||
| 21 | return "".join(aschr(_) for _ in line) | ||
| 22 | def hexdump(ofs, data): | ||
| 23 | for o in range(0, len(data), 16): | ||
| 24 | print("%08x: %-47s %s" % (o+ofs, ashex(data[o:o+16]), asasc(data[o:o+16]))) | ||
| 25 | |||
| 26 | def tohex(data): | ||
| 27 | return b2a_hex(data).decode('ascii') | ||
diff --git a/koddecoder.py b/koddecoder.py new file mode 100644 index 0000000..b98ffe6 --- /dev/null +++ b/koddecoder.py | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | """ | ||
| 2 | Decode CroStru KOD encoding. | ||
| 3 | """ | ||
| 4 | KOD = [ | ||
| 5 | 0x08, 0x63, 0x81, 0x38, 0xa3, 0x6b, 0x82, 0xa6, 0x18, 0x0d, 0xac, 0xd5, | ||
| 6 | 0xfe, 0xbe, 0x15, 0xf6, 0xa5, 0x36, 0x76, 0xe2, 0x2d, 0x41, 0xb5, 0x12, | ||
| 7 | 0x4b, 0xd8, 0x3c, 0x56, 0x34, 0x46, 0x4f, 0xa4, 0xd0, 0x01, 0x8b, 0x60, | ||
| 8 | 0x0f, 0x70, 0x57, 0x3e, 0x06, 0x67, 0x02, 0x7a, 0xf8, 0x8c, 0x80, 0xe8, | ||
| 9 | 0xc3, 0xfd, 0x0a, 0x3a, 0xa7, 0x73, 0xb0, 0x4d, 0x99, 0xa2, 0xf1, 0xfb, | ||
| 10 | 0x5a, 0xc7, 0xc2, 0x17, 0x96, 0x71, 0xba, 0x2a, 0xa9, 0x9a, 0xf3, 0x87, | ||
| 11 | 0xea, 0x8e, 0x09, 0x9e, 0xb9, 0x47, 0xd4, 0x97, 0xe4, 0xb3, 0xbc, 0x58, | ||
| 12 | 0x53, 0x5f, 0x2e, 0x21, 0xd1, 0x1a, 0xee, 0x2c, 0x64, 0x95, 0xf2, 0xb8, | ||
| 13 | 0xc6, 0x33, 0x8d, 0x2b, 0x1f, 0xf7, 0x25, 0xad, 0xff, 0x7f, 0x39, 0xa8, | ||
| 14 | 0xbf, 0x6a, 0x91, 0x79, 0xed, 0x20, 0x7b, 0xa1, 0xbb, 0x45, 0x69, 0xcd, | ||
| 15 | 0xdc, 0xe7, 0x31, 0xaa, 0xf0, 0x65, 0xd7, 0xa0, 0x32, 0x93, 0xb1, 0x24, | ||
| 16 | 0xd6, 0x5b, 0x9f, 0x27, 0x42, 0x85, 0x07, 0x44, 0x3f, 0xb4, 0x11, 0x68, | ||
| 17 | 0x5e, 0x49, 0x29, 0x13, 0x94, 0xe6, 0x1b, 0xe1, 0x7d, 0xc8, 0x2f, 0xfa, | ||
| 18 | 0x78, 0x1d, 0xe3, 0xde, 0x50, 0x4e, 0x89, 0xb6, 0x30, 0x48, 0x0c, 0x10, | ||
| 19 | 0x05, 0x43, 0xce, 0xd3, 0x61, 0x51, 0x83, 0xda, 0x77, 0x6f, 0x92, 0x9d, | ||
| 20 | 0x74, 0x7c, 0x04, 0x88, 0x86, 0x55, 0xca, 0xf4, 0xc1, 0x62, 0x0e, 0x28, | ||
| 21 | 0xb7, 0x0b, 0xc0, 0xf5, 0xcf, 0x35, 0xc5, 0x4c, 0x16, 0xe0, 0x98, 0x00, | ||
| 22 | 0x9b, 0xd9, 0xae, 0x03, 0xaf, 0xec, 0xc9, 0xdb, 0x6d, 0x3b, 0x26, 0x75, | ||
| 23 | 0x3d, 0xbd, 0xb2, 0x4a, 0x5d, 0x6c, 0x72, 0x40, 0x7e, 0xab, 0x59, 0x52, | ||
| 24 | 0x54, 0x9c, 0xd2, 0xe9, 0xef, 0xdd, 0x37, 0x1e, 0x8f, 0xcb, 0x8a, 0x90, | ||
| 25 | 0xfc, 0x84, 0xe5, 0xf9, 0x14, 0x19, 0xdf, 0x6e, 0x23, 0xc4, 0x66, 0xeb, | ||
| 26 | 0xcc, 0x22, 0x1c, 0x5c, | ||
| 27 | ] | ||
| 28 | def kodecode(o, data): | ||
| 29 | global KOD | ||
| 30 | return bytes((KOD[b] - i - o)%256 for i, b in enumerate(data)) | ||
| 31 | |||
| 32 | |||
