summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoritsme <itsme@xs4all.nl>2021-07-06 19:26:42 +0200
committeritsme <itsme@xs4all.nl>2021-07-06 19:26:42 +0200
commita9886b9d52c3bce0a4b58805b5597efccc55225a (patch)
tree4133e30e57109385ade3f756970058fe1edac255
initial commit
-rw-r--r--README.md19
-rw-r--r--crodump.py160
-rw-r--r--docs/exe-packer-notes.txt436
-rw-r--r--hexdump.py27
-rw-r--r--koddecoder.py32
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
5There is the `kodump` option, which does low level deobfuscation at arbitrary offsets,
6optionally deobfuscating with all possible `shift` values.
7
8Then 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
18see 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 @@
1import os.path
2import struct
3from binascii import b2a_hex
4from hexdump import hexdump, asasc, tohex
5from koddecoder import kodecode
6"""
7python3 crodump.py crodump chechnya_proverki_ul_2012
8python3 crodump.py kodump -s 6 -o 0x4cc9 -e 0x5d95 chechnya_proverki_ul_2012/CroStru.dat
9"""
10
11class 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
47class 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
66def 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
89def 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
112def 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
129def 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
158if __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 @@
137491b1b85fdf3969c45e83aa2d205ed = md5(plus/Cronos.exe)
2
3dump -o 0x314f7b -4 -l 0x810 plus/Cronos.exe
4
50x100000000-0x1947A71E = 0xE6B858E2
6
7add 4C27824Bh
8sub 47878428h
9sub 1DE7A541h
10
11
12seg000:00401000 start proc near
13seg000:00401000 push offset loc_F82001
14seg000:00401005 call nullsub_1
15seg000:0040100A retn
16seg000:0040100B nullsub_1:
17seg000: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----------------
286wWinMain(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
302loc_F82001: ; DATA XREF: start↑o
303 pusha
304 call loc_F82014
305loc_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
317loc_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
337loc_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
351loc_F8216E: ; CODE XREF: .data:00F8215A↑j
352 jo loc_F82176
353 push ebx
354 pop esi
355
356loc_F82176: ; CODE XREF: .data:loc_F8216E↑j
357 jmp loc_F82121
358
359
360
361
362dword_F82048 dd 0 ; DATA XREF: .data:00F8203F↑o
363 ; .data:00F8209B↓r ...
364 dd 0
365dword_F82050 dd 0 ; DATA XREF: .data:00F820B1↓r
366dword_F82054 dd 0 ; DATA XREF: .data:00F82092↓r
367 dd 0
368 dd 0
369byte_F82060 db 0 ; DATA XREF: .data:00F82022↑r
370dword_F82061 dd 0 ; DATA XREF: .data:00F8202F↑w
371 ; .data:00F8206C↓r ...
372
373loc_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
385loc_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
398loc_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
408loc_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
417loc_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
427loc_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 @@
1import struct
2from binascii import b2a_hex
3"""
4Simple hexdump, 16 bytes per line with offset.
5"""
6
7def ashex(line):
8 return " ".join("%02x" % _ for _ in line)
9def 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 "."
20def asasc(line):
21 return "".join(aschr(_) for _ in line)
22def 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
26def 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"""
2Decode CroStru KOD encoding.
3"""
4KOD = [
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]
28def kodecode(o, data):
29 global KOD
30 return bytes((KOD[b] - i - o)%256 for i, b in enumerate(data))
31
32