// IDA IDC script to decrypt encrypted strings in the Zeus/Zbot 2 malware.
// <interestingmalware@gmail.com>
#include "idc.idc"
static main() {
auto table = LocByName("_encrypted_strings");
auto decrypta = LocByName("GetEncryptedStringA");
auto decryptw = LocByName("GetEncryptedStringW");
Message("Decrypting string table\n");
fix_table(table);
Message("Commenting calls to %s\n", NameEx(BADADDR, decrypta));
comment_calls(decrypta, table);
Message("Commenting calls to %s\n", NameEx(BADADDR, decryptw));
comment_calls(decryptw, table);
}
static fix_table(table) {
auto entry;
auto xorval, length, data;
auto index, i, s;
entry = table;
while(1) {
MakeWord(entry);
xorval = Word(entry);
MakeWord(entry + 2);
length = Word(entry + 2);
if(length == 0) return;
data = Dword(entry + 4);
s = strfill(0, length+1);
for(i=0; i<length; i++) {
s[i] = (Byte(data + i) - length) ^ xorval;
}
// fix up disassembly
MakeNameEx(data, sprintf("EncString_%.2X", index), SN_CHECK);
MakeComm(entry + 4, s);
// do next entry
entry = entry + 8;
index = index + 1;
}
}
static comment_calls(func, table) {
auto x, t;
auto prev;
auto op;
auto comm;
// find all references to specified function
for(x=RfirstB(func); x != BADADDR; x = RnextB(func, x)) {
// check xref type to make sure it's a call
t = XrefType();
if(t == fl_CF || t == fl_CN) {
// check if previous instruction is 'pop eax'
prev = PrevHead(x, MinEA());
if(GetMnem(prev) == "pop" && GetOpnd(prev, 0) == "eax") {
// now look for the push
for(; prev != BADADDR; prev = PrevHead(prev, MinEA())) {
if(GetMnem(prev) == "push") {
// if we found a push, add a comment for the string
op = GetOperandValue(prev, 0);
comm = CommentEx(table + (op * 8) + 4, 0);
// add comment to call
MakeComm(x, comm);
break;
}
}
}
}
}
}