// Detect It Easy: detection rule file
// Author: horsicq <horsicq@gmail.com>

meta("installer", "Inno Setup Module");

function getVersionAndOptions(nOffset) {
    var sRawVersion = PE.getString(nOffset);
    sVersion = sRawVersion.substring(0, sRawVersion.indexOf(')'));
    if (/\(u\)/.test(sRawVersion)) {
        sOptions = sOptions.append("unicode");
    } else if (/\(a\)/.test(sRawVersion)) {
        sOptions = sOptions.append("ANSI");
    }
}

function getVersion(sSection) {
    if (PE.section[sSection]) {
        var nOffset = PE.section[sSection].FileOffset,
            nSize = PE.section[sSection].FileSize;

        if (nSize < 0x4000) {  // There are files with "data" section's size more as 0x2000
            var nInno = PE.findString(nOffset, nSize, "Inno Setup Setup Data");
            if (nInno != -1) {
                getVersionAndOptions(nInno + 23);
                return true;
            } else {
                nInno = PE.findSignature(nOffset, nSize, "'i1.'............'32'1A");
                if (nInno != -1) {
                    sVersion = PE.getString(nInno + 1).replace(/-.*/, "");
                    return true;
                }
            }
        }
    }

    return false;
}

function detect() {
    if (PE.compareOverlay("'zlb'1A") || PE.compareOverlay("'idska32'1A")) {
        if (!getVersion("DATA")) {
            getVersion(".data");
        }

        bDetected = true;
    } else {
        if (PE.getString(0x30, 4) == "InUn") {
            sOptions = "uninstall";
            var nOffset = PE.findString(PE.getOverlayOffset(), Math.min(0x100, PE.getOverlaySize()), "Inno Setup Messages");

            if (nOffset != -1) {
                getVersionAndOptions(nOffset + 21);
                bDetected = true;
            }

            if (!bDetected) {
                nOffset = PE.findString(PE.section[0].FileOffset, PE.section[0].FileSize, "Inno Setup version");
                if (nOffset != -1) {
                    getVersionAndOptions(nOffset + 19);
                    bDetected = true;
                }
            }

            if (!bDetected) {
                if (getVersion("DATA") || getVersion(".data")) {
                    bDetected = true;
                }
            }
        }
    }

    if (!bDetected) {
        if (PE.compareOverlay("'Inno Setup Messages'")) {
            sOptions = "uninstall";
            getVersionAndOptions(PE.getOverlayOffset() + 21);
            bDetected = true;
        } else if (PE.compareOverlay("'Inno Setup Setup Data'")) {
            getVersionAndOptions(PE.getOverlayOffset() + 23);
            bDetected = true;
        }
    }

    if (PE.compareOverlay("78da")) {
        sOptions = "zlib";
        if (PE.compareEP("558bec83c4..53565733c08945..8945")) {
            bDetected = true;
        } else if (PE.compareEP("558bec83c4..e8........e8........e8")) {
            bDetected = true;
        }
    } else if (PE.compareOverlay("'Inno'", 0x34)) {
        sOptions = "with stub";
        bDetected = true;
    }
    if (!bDetected) {
        if (PE.isNet()) {
            if (PE.getVersionStringInfo("Comments") == "This installation was built with Inno Setup.") {
                bDetected = true;
            }
        }
    }

    return result();
}