Gozi / ISFB
1. Executive Summary
The analyzed artifact is a packed 32-bit Windows PE DLL associated with the Gozi/ISFB malware family. The visible packed layer implements loader behavior, encrypted string storage, manual API resolution, executable memory allocation, and staged control transfer into an unpacked DLL image.
The original packed sample hides key runtime strings behind a compact byte-subtraction cipher. The relevant packed-stage decoder is located at 0x0040BDF0, with the byte-transform helper at 0x00401270. Recovered plaintext from this layer includes ntdll.dll, kernel32.dll, LdrGetProcedureAddress, and VirtualAlloc.
After unpacking and remapping, the next stage is a 32-bit DLL with a stale PE header ImageBase of 0x10000000, while code operands target 0x0040xxxx. The correct effective analysis base is therefore 0x00400000. Failure to rebase breaks absolute references, IAT references, and control-flow recovery.
The unpacked/remapped DLL contains two important decode paths:
| Routine | Address | Purpose |
|---|---|---|
| Packed string decoder | 0x0040BDF0 | Recovers loader strings in the packed stage. |
| Byte helper | 0x00401270 | Performs the rolling byte subtraction transform. |
| Resource/string-table resolver | 0x004011DE | Resolves and decrypts compressed metadata-backed entries. |
| Custom decompressor | 0x004016EE | Expands compressed resource entries. |
.bss decoder wrapper | 0x0040197C | Reconstructs runtime API-name data in .bss. |
.bss transform helper | 0x00401FD8 | Dword delta transform used by the .bss decode path. |
Primary capability observed in the inspected layers: staged loader execution, encrypted API-name storage, dynamic API resolution, private heap initialization, thread creation, Native API preparation, section mapping primitives, and memory protection control.
2. File Identification & IoCs
2.1 Packed DLL
| Field | Value |
|---|---|
| File size | 442,368 bytes |
| File type | PE32 DLL |
| Architecture | x86 / Intel 80386 |
| Image base | 0x00400000 |
| Entry point | RVA 0x00001430 / VA 0x00401430 |
| MD5 | f28f39ada498d66c378fd59227e0f215 |
| SHA-1 | 1c9c0584ad51f5be3f16b334d758c88b8cdb7b38 |
| SHA-256 | 0a66e8376fc6d9283e500c6e774dc0a109656fd457a0ce7dbf40419bc8d50936 |
| Linker / compile timestamp | 2004-08-04 07:57:05 UTC |
| PDB path | d:\in\the\town\where\ahung.pdb |
| Export status | No export observed in the packed layer |
The packed-stage timestamp should not be used as attribution. The section layout and loader behavior indicate deliberate packing/protection.
2.2 Unpacked / Remapped DLL
| Field | Value |
|---|---|
| Filename | _unpacked_gozi_remap.bin |
| Container | _unpacked_gozi_remap.zip |
| ZIP password | infected |
| Internal export DLL name | era.dll |
| File size | 57,344 bytes / 0xE000 |
| File type | PE32 DLL |
| Architecture | x86 / Intel 80386 |
| Subsystem | Windows GUI |
| Effective analysis base | 0x00400000 |
| PE header ImageBase | 0x10000000 |
| Entry point | RVA 0x1846 / effective VA 0x401846 |
| Exported function | DllRegisterServer at RVA 0x11C2 / effective VA 0x4011C2 |
| Compilation timestamp | 2022-04-26 19:11:46 UTC / 0x626843F2 |
| MD5 | fe0b06118973026ea5292ab09cc201e2 |
| SHA-1 | 0aaaabb5ef0084d175a3773688273b0943ed81e2 |
| SHA-256 | 7226f419ba40c25ac736484149163f0769c59c030ec0b91d3194d2dbf685ee99 |
2.3 Extracted Decrypted Resource Output
| Field | Value |
|---|---|
| Output name | gozi_dec_02d8_9e154a0c.bin |
| Source table entry | 0x2D8 |
| Source RVA | 0x6400 |
| Source file offset | 0x6400 |
| Decrypted size | 0xAE00 bytes |
| First DWORD fix key | 0xD8E1F12F |
| Expected fixed header | MZ / 4D 5A 90 00 |
| MD5 | 84667eac73ed93b5ec82ba94082e7c81 |
| SHA-1 | 98cc4f958e12928f9bf189bbed515afe1c635be7 |
| SHA-256 | 3c6abfece35d9dae5eebd0cc855d02615ed5f5c649bbeb55b27ef23003610a30 |
2.4 Network IoCs
No C2 domain, IP address, URI, or port was recovered from the inspected stages. The available artifacts are loader/decryption layers, not a confirmed network-beaconing configuration stage.
2.5 Host IoCs
| Type | Value | Confidence | Notes |
|---|---|---|---|
| Packed DLL SHA-256 | 0a66e8376fc6d9283e500c6e774dc0a109656fd457a0ce7dbf40419bc8d50936 | High | Original submitted packed sample. |
| Unpacked DLL SHA-256 | 7226f419ba40c25ac736484149163f0769c59c030ec0b91d3194d2dbf685ee99 | High | Current unpacked/remapped file used for stage 7 analysis. |
| PDB path | d:\in\the\town\where\ahung.pdb | Medium | Static artifact from packed DLL; may be noise. |
| Event object | Runtime supplied | Low | CreateEventA imported/used, but plaintext object name was not recovered in this pass. |
| Registry key | Not observed | N/A | No registry persistence confirmed from the inspected stage. |
| Mutex | Not observed | N/A | No mutex recovered statically. |
| Dropped file | Not observed | N/A | No filesystem drop confirmed statically. |
3. Static Analysis
3.1 Packed DLL Section Characteristics
Packed DLL entropy profile
| Section | RVA | Virtual Size | Raw Offset | Raw Size | Characteristics | Entropy | Assessment |
|---|---|---|---|---|---|---|---|
.text | 0x00001000 | 0x0000B710 | 0x00001000 | 0x0000C000 | Code / execute / read | 1.022 | Low entropy loader stub / sparse code. |
.rdata | 0x0000D000 | 0x00001073 | 0x0000D000 | 0x00002000 | Initialized data / read | 3.716 | Import descriptors, metadata, static strings. |
.data | 0x0000F000 | 0x000079D0 | 0x0000F000 | 0x00006000 | Initialized data / read-write | 6.027 | Mixed data, encrypted buffers, writable state. |
.crt | 0x00017000 | 0x0001DC8E | 0x00015000 | 0x0001E000 | Initialized data / read-write | 7.982 | High entropy packed/encrypted payload data. |
.erloc | 0x00035000 | 0x0002CA4F | 0x00033000 | 0x0002D000 | Initialized data / read-write | 7.981 | Non-standard relocation-like section, likely packed data. |
.rsrc | 0x00062000 | 0x00009F28 | 0x00060000 | 0x0000A000 | Initialized data / read | 6.517 | Resource section with elevated entropy. |
The packed file uses abnormal section naming and high-entropy writable sections. .crt and .erloc are the strongest indicators of embedded encrypted/compressed material.
3.2 Unpacked DLL Section Characteristics
| Section | RVA | Virtual Size | Raw Offset | Raw Size | Entropy | Notes |
|---|---|---|---|---|---|---|
.text | 0x1000 | 0x16B7 | 0x1000 | 0x16B7 | 6.551 | Code, loader logic, decompressor, SEH helpers. |
.rdata | 0x3000 | 0x059C | 0x3000 | 0x059C | 5.579 | Import descriptors, IAT, metadata. |
.data | 0x4000 | 0x025C | 0x4000 | 0x025C | 0.321 | Runtime state and globals. |
.bss | 0x5000 | 0x02DC | 0x5000 | 0x02DC | 7.620 | High-entropy encoded runtime API-name data. |
.reloc | 0x6000 | 0x8000 | 0x6000 | 0x8000 | 7.385 | Compressed/encrypted blob storage, not only relocation data. |
The .bss and .reloc names are misleading. Both sections carry encoded or compressed runtime material.
3.3 Imports and Exports
Packed import view
Unpacked DLL Imports
| DLL | APIs |
|---|---|
ntdll.dll | _snwprintf, memset, NtQuerySystemInformation, _aulldiv, RtlUnwind, NtQueryVirtualMemory |
KERNEL32.dll | SetThreadAffinityMask, CloseHandle, HeapAlloc, SetThreadPriority, Sleep, ExitThread, lstrlenW, GetLastError, GetExitCodeThread, HeapCreate, HeapDestroy, GetCurrentThread, SleepEx, WaitForSingleObject, InterlockedDecrement, InterlockedIncrement, HeapFree, GetModuleFileNameW, SetLastError, GetModuleHandleA, VirtualProtect, OpenProcess, CreateEventA, GetLongPathNameW, GetVersion, GetCurrentProcessId, TerminateThread, QueueUserAPC, CreateThread, GetProcAddress, LoadLibraryA, VirtualFree, VirtualAlloc, MapViewOfFile, GetSystemTimeAsFileTime, CreateFileMappingW |
ADVAPI32.dll | ConvertStringSecurityDescriptorToSecurityDescriptorA |
Notable primitives: VirtualAlloc, VirtualProtect, CreateThread, QueueUserAPC, OpenProcess, MapViewOfFile, CreateFileMappingW, NtQueryVirtualMemory, and NtQuerySystemInformation.
The unpacked DLL exports DllRegisterServer, consistent with a COM-registration style entry point but not necessarily benign COM behavior.
4. Behavioral & Dynamic Analysis
4.1 Execution Handling
The packed sample acts as a loader. It resolves minimal APIs, allocates executable memory, reconstructs the next image, applies memory permissions, and transfers control into the unpacked DLL.
The unpacked DLL entry point is 0x401846. Its initialization path performs process/thread attach accounting, creates a private heap, prepares runtime state, decodes internal data, and starts worker logic.
| Address | Behavior |
|---|---|
0x401846 | DLL entry-style dispatcher. Handles attach/detach reason values. |
0x401863 | Uses InterlockedIncrement for attach state tracking. |
0x40187D | Creates a private heap via HeapCreate. |
0x4018A6 | Calls SEH/setup helper at 0x401EFE. |
0x4018AC | Enters worker-thread setup through 0x402009. |
0x40197C | Decodes .bss, validates checksum, and copies decoded bytes back. |
0x401BC9 | Uses decoded/resolved data in timing/sleep logic. |
4.2 Process Tree / Injection / Persistence
No process hollowing, registry persistence, dropped file, or network callback was confirmed from the inspected stage. However, the import set and decoded .bss API names expose primitives commonly used by loaders and injection-capable malware:
ZwCreateSectionZwMapViewOfSectionZwUnmapViewOfSectionZwWriteVirtualMemoryZwProtectVirtualMemoryZwSetContextThreadZwGetContextThreadQueueUserAPCCreateThreadOpenProcess
The safest conclusion is that this stage prepares mapping/injection capability, but the full injection target and C2 configuration were not present in plaintext in the submitted layer.
5. Deep Dive: Packed Stage String Decryption
5.1 Scope
The packed stage contains a string decryption routine at 0x0040BDF0. The helper at 0x00401270 performs a byte subtraction transform using a rolling index into a 16-byte key.
5.2 Byte Helper Function: 0x00401270
Byte helper in decompiler
00401270 push ebp
00401271 mov ebp, esp
00401273 push esi
00401274 mov al, byte ptr [ebp+14h] ; key byte
00401277 mov ecx, dword ptr [ebp+10h] ; index
0040127A mov edx, dword ptr [ebp+0Ch] ; encrypted source
0040127D mov esi, dword ptr [ebp+08h] ; destination
00401280 mov ah, byte ptr [edx+ecx]
00401283 sub ah, al
00401285 mov byte ptr [esi+ecx], ah
00401288 pop esi
00401289 pop ebp
0040128A ret
Reconstructed helper:
1
2
3
void transform_byte(uint8_t *dst, const uint8_t *src, uint32_t i, uint8_t key_byte) {
dst[i] = src[i] - key_byte;
}
5.3 Decoder Loop: 0x0040BDF0
The malware does not use XOR for this layer. It uses byte subtraction with a 16-byte rolling key.
Key at 0x0040DBF6:
1
EC FB 05 08 DC D1 23 6F 67 44 5F 42 D8 77 DC 56
Algorithm:
1
2
3
4
5
6
7
8
9
10
void decrypt_string(uint8_t *dst, const uint8_t *src, uint32_t len) {
static const uint8_t key[16] = {
0xEC, 0xFB, 0x05, 0x08, 0xDC, 0xD1, 0x23, 0x6F,
0x67, 0x44, 0x5F, 0x42, 0xD8, 0x77, 0xDC, 0x56
};
for (uint32_t i = 0; i < len; i++) {
dst[i] = (uint8_t)(src[i] - key[i & 0x0F]);
}
}
Inverse operation, useful for validation:
1
enc[i] = (uint8_t)(plain[i] + key[i & 0x0F]);
Decoder loop highlight
The decoder iterates over an encrypted buffer, applies the helper per byte, and writes plaintext back into the destination buffer. The key schedule is short and cyclic. The transform is reversible without running the malware.
Recovered packed-stage plaintext strings:
1
2
3
4
ntdll.dll
kernel32.dll
LdrGetProcedureAddress
VirtualAlloc
5.4 Manual API Resolution
The recovered strings support a loader path that manually resolves LdrGetProcedureAddress and VirtualAlloc. This reduces reliance on a clear static import table and delays key API visibility until runtime.
5.5 Anti-Analysis Notes
| Technique | Evidence |
|---|---|
| Packed high-entropy regions | .crt, .erloc, and .rsrc entropy profile. |
| Encrypted API strings | Packed-stage string decoder at 0x0040BDF0. |
| Manual API resolution | Recovered LdrGetProcedureAddress and VirtualAlloc. |
| Loader control transfer | Dynamic unpacking into memory before remapped-stage execution. |
6. Dynamic Unpacking and Remap
6.1 Breakpoints Used
The unpacking workflow used memory-allocation and protection pivots to identify the unpacked image in memory.
VirtualAlloc and VirtualProtect breakpoints
Recommended breakpoint targets for this style of loader:
| API | Purpose |
|---|---|
VirtualAlloc | Catch new image allocation. |
VirtualProtect | Catch transition to executable permissions. |
WriteProcessMemory / ZwWriteVirtualMemory | Catch remote/local image write if used. |
CreateThread / QueueUserAPC | Catch execution handoff. |
LoadLibraryA/W and GetProcAddress | Catch dynamic API resolution. |
6.2 Unpacked Image in Memory
Unpacked image in memory
The unpacked dump contains a valid PE-like image and a working import table. The entry point used for analysis is 0x401846 after rebasing to 0x00400000.
6.3 Remap Correction
Remap before and after
The remapped file keeps a stale PE header image base of 0x10000000, while absolute code references point to 0x0040xxxx. The correct static analysis workflow is:
- Load the dumped DLL.
- Rebase to
0x00400000. - Re-run analysis.
- Repair function boundaries where the unpacker damaged normal metadata.
- Rebuild imports/xrefs around
0x4030xxIAT references.
7. Unpacked and Remapped DLL Analysis
7.1 Rebasing Issue
The PE Optional Header reports ImageBase = 0x10000000, but the code uses absolute operands such as:
40146A ff 15 54 30 40 00 call dword ptr ds:0x403054 ; GetModuleHandleA
401485 ff d7 call edi ; GetProcAddress
4019D2 ff 15 88 30 40 00 call dword ptr ds:0x403088 ; VirtualAlloc
These operands prove the effective base is 0x00400000.
7.2 Resource/String-Table Resolver: 0x4011DE
The resolver derives two values from global key material:
1
2
entry_tag = (global_key ^ 0x150E) & 0xFFFF;
table_delta = global_key ^ 0x69B25F5C;
Recovered values:
1
2
3
global_key = 0x69B25F44
entry_tag = 0x4A4A
table_delta = 0x18
The metadata table begins at:
1
2
PE + SizeOfOptionalHeader + ((NumberOfSections + 1) * 0x28) + table_delta
= 0x2D8
Recovered table entry:
| Field | Value |
|---|---|
| Table offset | 0x2D8 |
| Entry tag | 0x4A4A |
| Flags | 0x21 |
| XOR key | 0xD8E1F12F |
| Selector | 0x9E154A0C |
| Data RVA | 0x6400 |
| Data file offset | 0x6400 |
| Decrypted size | 0xAE00 |
Relevant assembly:
401204 8b ce mov ecx, esi
401206 81 f1 0e 15 00 00 xor ecx, 150Eh
401212 0f b7 c9 movzx ecx, cx
401215 81 f6 5c 5f b2 69 xor esi, 69B25F5Ch
401236 8b 45 10 mov eax, [ebp+10h]
40123D 39 46 08 cmp [esi+8], eax
401248 8b 46 10 mov eax, [esi+10h]
401264 8b 46 0c mov eax, [esi+0Ch]
40126A e8 7f 04 00 00 call 4016EEh
401281 8b 46 04 mov eax, [esi+4]
401284 31 03 xor [ebx], eax
The flags & 1 branch invokes the decompressor. After decompression, the first DWORD of the output buffer is XOR-fixed using the entry key.
1
2
3
compressed output first DWORD : 0xD871AB62
XOR key : 0xD8E1F12F
result : 0x00905A4D => 4D 5A 90 00
7.3 Custom Decompressor: 0x4016EE
The decompressor is bitstream-based and uses MSB-first bit extraction. Its structure is compatible with an aPLib-style back-reference depacker.
Pseudocode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
out[0] = src[0];
src++;
while (!done) {
if (getbit() == 0) {
*dst++ = *src++;
} else if (getbit() == 0) {
distance = gamma_decode();
length = gamma_decode();
length += threshold_adjust(distance);
copy_from_backref(distance, length);
} else if (getbit() == 0) {
token = *src++;
distance = token >> 1;
length = (token & 1) + 2;
if (distance == 0)
break;
copy_from_backref(distance, length);
} else {
distance = read_4_bits();
*dst++ = distance ? dst[-distance] : 0;
}
}
Length adjustment at 0x401E48:
1
2
3
4
5
6
if (distance < 0x80)
length += 2;
if (distance >= 0x500)
length += 1;
if (distance >= 0x7D00)
length += 1;
7.4 Anti-Analysis Observations
| Technique | Evidence |
|---|---|
| Stale / incorrect image base | Header says 0x10000000; code operands target 0x0040xxxx. |
| Encoded high-entropy sections | .bss and .reloc store encoded/compressed data. |
| Runtime API resolution | Loader resolves APIs through decoded strings and GetProcAddress. |
| Runtime memory inspection | Uses NtQueryVirtualMemory. |
| System information query | Uses NtQuerySystemInformation. |
| Thread and timing control | Uses SetThreadAffinityMask, SetThreadPriority, SleepEx, WaitForSingleObject. |
| SEH scaffolding | Custom SEH helpers around 0x402228, 0x40227C, and related routines. |
8. .bss Runtime Decode
The remapped stage keeps high-entropy encoded data in a pseudo-.bss section. This is separate from the 0x4011DE resource/string-table resolver.
Relevant routines:
| VA | Purpose |
|---|---|
0x401922 | Locates the section header named .bss and returns its RVA/size. |
0x40197C | Main .bss decode wrapper; allocates scratch memory, decodes data, validates checksum, copies bytes back. |
0x401FD8 | Dword delta transform loop. |
0x40212B | Internal memcpy-style routine. |
Transform:
1
2
3
key = dword(0x4030B8) + dword(0x4030BC) + bss_rva + seed - 1
out = encoded_dword + previous_encoded_dword - key
stop = first zero encoded_dword
Recovered values:
1
2
3
4
5
6
.bss RVA = 0x5000
.bss size = 0x2DC
valid seed = 0x13
key = 0x5292F685
checksum = 0x69B25F44
marker offset = 0x1BA
Decoded .bss strings:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
NTDLL.DLL
NTDSAPI.DLL
KERNEL32.DLL
IsWow64Process
Wow64EnableWow64FsRedirection
ZwCreateSection
ZwMapViewOfSection
ZwUnmapViewOfSection
RtlNtStatusToDosError
ZwClose
ZwSetContextThread
ZwGetContextThread
ZwWow64ReadVirtualMemory64
ZwWow64QueryInformationProcess64
kernelbase
LdrRegisterDllNotification
LdrUnregisterDllNotification
ZwWriteVirtualMemory
ZwProtectVirtualMemory
LoadLibraryA
These strings explain the later Native API resolution path and strongly indicate section-mapping and memory-modification capability.
9. MITRE ATT&CK Mapping
| Tactic | Technique | Evidence |
|---|---|---|
| Defense Evasion | T1027 Obfuscated/Compressed Files and Information | Packed high-entropy sections, encrypted strings, compressed internal blob. |
| Defense Evasion | T1140 Deobfuscate/Decode Files or Information | Runtime string/resource decryption and .bss reconstruction. |
| Defense Evasion | T1497 Virtualization/Sandbox Evasion | Environment and memory query primitives through NtQuerySystemInformation and NtQueryVirtualMemory; no full VM check confirmed. |
| Execution | T1055 Process Injection | Native APIs and imports support section mapping and remote memory modification; injection flow not fully confirmed in submitted stage. |
| Execution | T1106 Native API | Decoded Zw* names and imported Native API usage. |
| Privilege / Defense Evasion | T1098 / local manipulation not confirmed | No registry/service/task persistence confirmed; do not overclaim. |
10. Detection Engineering
10.1 YARA Rule
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
rule MAL_Gozi_ISFB_Loader_Unpacked_Remapped_Stage
{
meta:
description = "Gozi/ISFB unpacked/remapped loader stage with encoded .bss and resource resolver"
author = "os1ris"
scope = "file"
malware_family = "Gozi/ISFB"
sha256_unpacked = "7226f419ba40c25ac736484149163f0769c59c030ec0b91d3194d2dbf685ee99"
strings:
$s1 = "DllRegisterServer" ascii
$s2 = "ConvertStringSecurityDescriptorToSecurityDescriptorA" ascii
$s3 = "NtQueryVirtualMemory" ascii
$s4 = "NtQuerySystemInformation" ascii
$bss_name = ".bss" ascii
$reloc_name = ".reloc" ascii
// 401206: xor ecx, 150Eh ; 401215: xor esi, 69B25F5Ch
$resolver_key_ops = { 81 F1 0E 15 00 00 [0-16] 81 F6 5C 5F B2 69 }
// 401284: xor [ebx], eax after decompression output
$first_dword_fix = { 8B 46 04 31 03 }
condition:
uint16(0) == 0x5A4D and
filesize < 2MB and
3 of ($s*) and
all of ($resolver_key_ops, $first_dword_fix)
}
10.2 Detection Notes
- Avoid hash-only detection. Use section characteristics, resolver constants, and API clusters.
- The
ImageBasemismatch is useful for triage, but not stable enough as a single detection condition. - The
.bssand.relocentropy pattern is a good hunting signal for this unpacked/remapped artifact.
Appendix A: References
- MITRE ATT&CK: Obfuscated Files or Information —
https://attack.mitre.org/techniques/T1027/ - MITRE ATT&CK: Deobfuscate/Decode Files or Information —
https://attack.mitre.org/techniques/T1140/ - MITRE ATT&CK: Process Injection —
https://attack.mitre.org/techniques/T1055/ - MITRE ATT&CK: Native API —
https://attack.mitre.org/techniques/T1106/ - Microsoft PE Format —
https://learn.microsoft.com/en-us/windows/win32/debug/pe-format
Appendix B: Script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import argparse
import struct
from pathlib import Path
BASE = 0x400000
BSS_RVA = 0x5000
BSS_OFF = 0x5000
BSS_SIZE = 0x2DC
K0 = 0x20727041
K1 = 0x32203632
CHECK = 0x69B25F44
def u32(b, o):
return struct.unpack_from('<I', b, o)[0]
def decode_bss(pe, seed):
src = pe[BSS_OFF:BSS_OFF + BSS_SIZE] + b'\x00' * (0x1000 - BSS_SIZE)
dst = bytearray(0x1000)
key = (K0 + K1 + BSS_RVA + seed - 1) & 0xFFFFFFFF
prev = 0
for off in range(0, 0x1000, 4):
enc = u32(src, off)
if enc == 0:
break
dec = (enc + prev - key) & 0xFFFFFFFF
struct.pack_into('<I', dst, off, dec)
prev = enc
marker = 0x1A7 + seed
checksum = (u32(dst, marker + 0x0C) - u32(dst, marker + 0x08) + u32(dst, marker + 0x04)) & 0xFFFFFFFF
return bytes(dst[:BSS_SIZE]), key, marker, checksum
def strings(data, min_len=4):
out = []
start = None
for i, c in enumerate(data + b'\x00'):
if 32 <= c <= 126:
if start is None:
start = i
else:
if start is not None and i - start >= min_len:
out.append((start, data[start:i].decode('latin1')))
start = None
return out
def main():
ap = argparse.ArgumentParser()
ap.add_argument('pe')
ap.add_argument('-o', '--out', default='gozi_decoded.bin')
args = ap.parse_args()
pe = Path(args.pe).read_bytes()
for seed in range(0x100):
dec, key, marker, checksum = decode_bss(pe, seed)
if checksum == CHECK:
Path(args.out).write_bytes(dec)
print(f'seed=0x{seed:x}')
print(f'key=0x{key:08x}')
print(f'marker_off=0x{marker:x}')
print(f'checksum=0x{checksum:08x}')
print(f'output={args.out}')
print()
for off, s in strings(dec):
print(f'0x{off:04x}: {s}')
return
raise SystemExit('no valid seed found')
if __name__ == '__main__':
main()









