41
44
/* #define LOGPARSEICONDETAILS */
48
unsigned int gcnt, hcnt; /* gcnt -> number of icon groups parsed, hcnt -> "actual" image count */
54
struct cli_exe_section *exe_sections;
58
uint32_t icnt; /* number of icon entries parsed, declared images */
61
uint32_t err_oof; /* parseicon: offset to icon is out of file */
62
uint32_t err_bhoof; /* parseicon: bmp header is out of file */
63
uint32_t err_bhts; /* parseicon: BMP header too small */
64
uint32_t err_tstl; /* parseicon: Image too small or too big */
65
uint32_t err_insl; /* parseicon: Image not square enough */
49
static int groupicon_cb(void *ptr, uint32_t type, uint32_t name, uint32_t lang, uint32_t rva) {
50
struct GICONS *gicons = ptr;
51
type = type; lang = lang;
52
cli_dbgmsg("groupicon_cb: got group %x\n", name);
53
if(!gicons->cnt || gicons->lastg == name) {
54
gicons->rvas[gicons->cnt] = rva;
68
int cli_groupiconscan(struct ICON_ENV *icon_env, uint32_t rva);
70
static int groupicon_scan_cb(void *ptr, uint32_t type, uint32_t name, uint32_t lang, uint32_t rva) {
71
struct ICON_ENV *icon_env = ptr;
73
type = type; lang = lang; /* Prevent compiler warnings regarding unused variables */
75
cli_dbgmsg("groupicon_cb: scanning group %x\n", name);
76
if(!icon_env->gcnt || icon_env->lastg == name) {
78
icon_env->lastg = name;
81
ret = cli_groupiconscan(icon_env, rva);
68
static int icon_cb(void *ptr, uint32_t type, uint32_t name, uint32_t lang, uint32_t rva) {
69
struct ICONS *icons = ptr;
70
type = type; lang = lang;
71
cli_dbgmsg("icon_cb: got icon %x\n", name);
74
icons->rvas[icons->cnt] = rva;
91
static int parseicon(struct ICON_ENV *icon_env, uint32_t rva);
93
static int icon_scan_cb(void *ptr, uint32_t type, uint32_t name, uint32_t lang, uint32_t rva) {
94
struct ICON_ENV *icon_env = ptr;
95
type = type; lang = lang; /* Prevent compiler warnings regarding unused variables */
96
//cli_dbgmsg("icon_cb: scanning icon %x\n", name);
99
icon_env->result = parseicon(icon_env, rva);
102
if (icon_env->result != CL_CLEAN)
80
static int parseicon(icon_groupset *set, uint32_t rva, cli_ctx *ctx, struct cli_exe_section *exe_sections, uint16_t nsections, uint32_t hdr_size);
82
108
int cli_scanicon(icon_groupset *set, uint32_t resdir_rva, cli_ctx *ctx, struct cli_exe_section *exe_sections, uint16_t nsections, uint32_t hdr_size) {
85
unsigned int curicon, err;
86
fmap_t *map = *ctx->fmap;
90
findres(14, 0xffffffff, resdir_rva, map, exe_sections, nsections, hdr_size, groupicon_cb, &gicons);
92
for(curicon=0; curicon<gicons.cnt; curicon++) {
93
const uint8_t *grp = fmap_need_off_once(map, cli_rawaddr(gicons.rvas[curicon], exe_sections, nsections, &err, map->len, hdr_size), 16);
95
uint32_t gsz = cli_readint32(grp + 4);
109
grp = fmap_need_off_once(map, cli_rawaddr(cli_readint32(grp), exe_sections, nsections, &err, map->len, hdr_size), gsz);
111
icnt = cli_readint32(grp+2) >> 16;
115
while(icnt && gsz >= 14) {
116
dir = (struct icondir *)grp;
117
cli_dbgmsg("cli_scanicon: Icongrp @%x - %ux%ux%u - (id=%x, rsvd=%u, planes=%u, palcnt=%u, sz=%x)\n", gicons.rvas[curicon], dir->w, dir->h, cli_readint16(&dir->depth), cli_readint16(&dir->id), cli_readint16(&dir->planes), dir->palcnt, dir->rsvd, cli_readint32(&dir->sz));
118
findres(3, cli_readint16(&dir->id), resdir_rva, map, exe_sections, nsections, hdr_size, icon_cb, &icons);
127
for(curicon=0; curicon<icons.cnt; curicon++) {
128
if(parseicon(set, icons.rvas[curicon], ctx, exe_sections, nsections, hdr_size) == CL_VIRUS)
109
struct ICON_ENV icon_env;
110
fmap_t *map = *ctx->fmap;
111
uint32_t err_total = 0;
118
icon_env.result = CL_CLEAN;
121
icon_env.resdir_rva = resdir_rva;
122
icon_env.exe_sections = exe_sections;
123
icon_env.nsections = nsections;
124
icon_env.hdr_size = hdr_size;
126
icon_env.max_icons = ctx->engine->maxiconspe;
128
icon_env.err_oof = 0;
129
icon_env.err_bhoof = 0;
130
icon_env.err_bhts = 0;
131
icon_env.err_tstl = 0;
132
icon_env.err_insl = 0;
134
/* icon group scan callback --> groupicon_scan_cb() */
135
findres(14, 0xffffffff, resdir_rva, map, exe_sections, nsections, hdr_size, groupicon_scan_cb, &icon_env);
137
/* CL_EMAXSIZE is used to track the icon limit */
138
if (icon_env.result == CL_EMAXSIZE)
139
cli_dbgmsg("cli_scanicon: max icon count reached\n");
141
cli_dbgmsg("cli_scanicon: scanned a total of %u[%u actual] icons across %u groups\n", icon_env.icnt, icon_env.hcnt, icon_env.gcnt);
142
if (icon_env.hcnt < icon_env.icnt)
143
cli_warnmsg("cli_scanicon: found %u invalid icon entries of %u total\n", icon_env.icnt-icon_env.hcnt, icon_env.icnt);
145
err_total = icon_env.err_oof + icon_env.err_bhoof + icon_env.err_bhts + icon_env.err_tstl + icon_env.err_insl;
147
cli_dbgmsg("cli_scanicon: detected %u total image parsing issues\n", err_total);
148
if (icon_env.err_oof > 0)
149
cli_dbgmsg("cli_scanicon: detected %u cases of 'parseicon: offset to icon is out of file'\n", icon_env.err_oof);
150
if (icon_env.err_bhoof > 0)
151
cli_dbgmsg("cli_scanicon: detected %u cases of 'parseicon: bmp header is out of file'\n", icon_env.err_bhoof);
152
if (icon_env.err_bhts > 0)
153
cli_dbgmsg("cli_scanicon: detected %u cases of 'parseicon: BMP header too small'\n", icon_env.err_bhts);
154
if (icon_env.err_tstl > 0)
155
cli_dbgmsg("cli_scanicon: detected %u cases of 'parseicon: Image too small or too big'\n", icon_env.err_tstl);
156
if (icon_env.err_insl > 0)
157
cli_dbgmsg("cli_scanicon: detected %u cases of 'parseicon: Image not square enough'\n", icon_env.err_insl);
160
/* ignore all error returns (previous behavior) */
161
if (icon_env.result == CL_VIRUS)
167
int cli_groupiconscan(struct ICON_ENV *icon_env, uint32_t rva)
169
/* import environment */
170
icon_groupset *set = icon_env->set;
171
uint32_t resdir_rva = icon_env->resdir_rva;
172
cli_ctx *ctx = icon_env->ctx;
173
struct cli_exe_section *exe_sections = icon_env->exe_sections;
174
uint16_t nsections = icon_env->nsections;
175
uint32_t hdr_size = icon_env->hdr_size;
178
fmap_t *map = *ctx->fmap;
179
const uint8_t *grp = fmap_need_off_once(map, cli_rawaddr(rva, exe_sections, nsections, &err, map->len, hdr_size), 16);
182
uint32_t gsz = cli_readint32(grp + 4);
184
uint32_t icnt, raddr;
185
unsigned int piconcnt;
197
raddr = cli_rawaddr(cli_readint32(grp), exe_sections, nsections, &err, map->len, hdr_size);
198
cli_dbgmsg("cli_scanicon: icon group @%x\n", raddr);
199
grp = fmap_need_off_once(map, raddr, gsz);
201
icnt = cli_readint32(grp+2) >> 16;
206
while(icnt && gsz >= 14 /* && (remaining amount of icons) */) {
207
piconcnt = icon_env->hcnt;
209
dir = (struct icondir *)grp;
210
cli_dbgmsg("cli_scanicon: Icongrp @%x - %ux%ux%u - (id=%x, rsvd=%u, planes=%u, palcnt=%u, sz=%x)\n", rva, dir->w, dir->h, cli_readint16(&dir->depth), cli_readint16(&dir->id), cli_readint16(&dir->planes), dir->palcnt, dir->rsvd, cli_readint32(&dir->sz));
212
/* icon scan callback --> icon_scan_cb() */
213
findres(3, cli_readint16(&dir->id), resdir_rva, map, exe_sections, nsections, hdr_size, icon_scan_cb, icon_env);
214
if (icon_env->result != CL_CLEAN)
215
return icon_env->result;
217
if (piconcnt == icon_env->hcnt)
218
cli_dbgmsg("cli_scanicon: invalid icon entry %u in group @%x\n", dir->id, rva);
223
if (icon_env->icnt >= icon_env->max_icons) {
224
icon_env->result = CL_EMAXSIZE;
225
return icon_env->result;
233
cli_dbgmsg("cli_scanicon: could not find %u icons\n", icnt);
235
cli_dbgmsg("cli_scanicon: could not parse %u bytes of icon entries\n", gsz);
240
return icon_env->result;