...
|
...
|
@@ -47,7 +47,7 @@ struct GICONS {
|
47
|
47
|
static int groupicon_cb(void *ptr, uint32_t type, uint32_t name, uint32_t lang, uint32_t rva) {
|
48
|
48
|
struct GICONS *gicons = ptr;
|
49
|
49
|
type = type; lang = lang;
|
50
|
|
- cli_dbgmsg("groupicon_cb: got group %u\n", name);
|
|
50
|
+ cli_dbgmsg("groupicon_cb: got group %x\n", name);
|
51
|
51
|
if(!gicons->cnt || gicons->lastg == name) {
|
52
|
52
|
gicons->rvas[gicons->cnt] = rva;
|
53
|
53
|
gicons->cnt++;
|
...
|
...
|
@@ -66,7 +66,7 @@ struct ICONS {
|
66
|
66
|
static int icon_cb(void *ptr, uint32_t type, uint32_t name, uint32_t lang, uint32_t rva) {
|
67
|
67
|
struct ICONS *icons = ptr;
|
68
|
68
|
type = type; lang = lang;
|
69
|
|
- cli_dbgmsg("icon_cb: got icon %u\n", name);
|
|
69
|
+ cli_dbgmsg("icon_cb: got icon %x\n", name);
|
70
|
70
|
if(icons->cnt > 100)
|
71
|
71
|
return 1;
|
72
|
72
|
icons->rvas[icons->cnt] = rva;
|
...
|
...
|
@@ -103,7 +103,7 @@ int cli_scanicon(icon_groupset *set, uint32_t resdir_rva, cli_ctx *ctx, struct c
|
103
|
103
|
uint32_t sz;
|
104
|
104
|
uint16_t id;
|
105
|
105
|
} *dir;
|
106
|
|
-
|
|
106
|
+
|
107
|
107
|
grp = fmap_need_off_once(map, cli_rawaddr(cli_readint32(grp), exe_sections, nsections, &err, map->len, hdr_size), gsz);
|
108
|
108
|
if(grp && !err) {
|
109
|
109
|
icnt = cli_readint32(grp+2) >> 16;
|
...
|
...
|
@@ -1201,6 +1201,7 @@ static int parseicon(icon_groupset *set, uint32_t rva, cli_ctx *ctx, struct cli_
|
1201
|
1201
|
fmap_t *map;
|
1202
|
1202
|
uint32_t icoff;
|
1203
|
1203
|
struct icon_matcher *matcher;
|
|
1204
|
+ unsigned int special_32_is_32 = 0;
|
1204
|
1205
|
|
1205
|
1206
|
if(!ctx || !ctx->engine || !(matcher=ctx->engine->iconcheck))
|
1206
|
1207
|
return CL_SUCCESS;
|
...
|
...
|
@@ -1228,7 +1229,7 @@ static int parseicon(icon_groupset *set, uint32_t rva, cli_ctx *ctx, struct cli_
|
1228
|
1228
|
|
1229
|
1229
|
/* seek to the end of v4/v5 header */
|
1230
|
1230
|
icoff += EC32(bmphdr.sz);
|
1231
|
|
-
|
|
1231
|
+
|
1232
|
1232
|
width = EC32(bmphdr.w);
|
1233
|
1233
|
height = EC32(bmphdr.h) / 2;
|
1234
|
1234
|
depth = EC16(bmphdr.depth);
|
...
|
...
|
@@ -1333,7 +1334,9 @@ static int parseicon(icon_groupset *set, uint32_t rva, cli_ctx *ctx, struct cli_
|
1333
|
1333
|
break;
|
1334
|
1334
|
case 32:
|
1335
|
1335
|
for(x=0; x<width; x++) {
|
1336
|
|
- imagedata[(height - 1 - y) * width + x] = rawimage[x_off] | (rawimage[x_off + 1] << 8) | (rawimage[x_off + 2] << 16) | (rawimage[x_off + 3] << 24);
|
|
1336
|
+ unsigned int a = rawimage[x_off + 3] << 24;
|
|
1337
|
+ imagedata[(height - 1 - y) * width + x] = rawimage[x_off] | (rawimage[x_off + 1] << 8) | (rawimage[x_off + 2] << 16) | a;
|
|
1338
|
+ special_32_is_32 |= a;
|
1337
|
1339
|
x_off+=4;
|
1338
|
1340
|
}
|
1339
|
1341
|
break;
|
...
|
...
|
@@ -1343,10 +1346,23 @@ static int parseicon(icon_groupset *set, uint32_t rva, cli_ctx *ctx, struct cli_
|
1343
|
1343
|
if(palette) fmap_unneed_ptr(map, palette, (1<<depth) * sizeof(int));
|
1344
|
1344
|
makebmp("0-noalpha", tempd, width, height, imagedata);
|
1345
|
1345
|
|
|
1346
|
+ if(depth == 32 && !special_32_is_32) { /* Sometimes it really is 24. Exploited live - see sample 0013839101 */
|
|
1347
|
+ andlinesz = 4*(width / 32) + 4*(width % 32 != 0);
|
|
1348
|
+ if(!(rawimage = fmap_need_off_once(map, icoff + height * scanlinesz, height * andlinesz))) {
|
|
1349
|
+ /* Likely a broken sample - 32bit icon with 24bit data and a broken mask:
|
|
1350
|
+ i could really break out here but i've got the full image, so i'm just forcing full alpha */
|
|
1351
|
+ for(y=0; y<height; y++)
|
|
1352
|
+ for(x=0; x<width; x++)
|
|
1353
|
+ imagedata[y * width + x] |= 0xff000000;
|
|
1354
|
+ special_32_is_32 = 0;
|
|
1355
|
+ cli_dbgmsg("parseicon: found a broken and stupid icon\n");
|
|
1356
|
+ } else cli_dbgmsg("parseicon: found a stupid icon\n");
|
|
1357
|
+ } else rawimage += height * scanlinesz;
|
|
1358
|
+
|
1346
|
1359
|
/* Set alpha on or off based on the mask */
|
1347
|
|
- if(depth & 0x1f) {
|
|
1360
|
+ if((depth & 0x1f) || !special_32_is_32) {
|
1348
|
1361
|
for(y=0; y<height; y++) {
|
1349
|
|
- unsigned int x_off = height * scanlinesz + y * andlinesz;
|
|
1362
|
+ unsigned int x_off = y * andlinesz;
|
1350
|
1363
|
unsigned int have = 0;
|
1351
|
1364
|
unsigned char c;
|
1352
|
1365
|
for(x=0; x<width; x++) {
|