... | ... |
@@ -111,8 +111,8 @@ if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) { \ |
111 | 111 |
|
112 | 112 |
#define CLI_TMPUNLK() if(!ctx->engine->keeptmp) { \ |
113 | 113 |
if (cli_unlink(tempfile)) { \ |
114 |
- free(tempfile); \ |
|
115 |
- return CL_EUNLINK; \ |
|
114 |
+ free(tempfile); \ |
|
115 |
+ return CL_EUNLINK; \ |
|
116 | 116 |
} \ |
117 | 117 |
} |
118 | 118 |
|
... | ... |
@@ -126,70 +126,70 @@ if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) { \ |
126 | 126 |
|
127 | 127 |
#define FSGCASE(NAME,FREESEC) \ |
128 | 128 |
case 0: /* Unpacked and NOT rebuilt */ \ |
129 |
- cli_dbgmsg(NAME": Successfully decompressed\n"); \ |
|
130 |
- close(ndesc); \ |
|
131 |
- if (cli_unlink(tempfile)) { \ |
|
132 |
- free(exe_sections); \ |
|
133 |
- free(tempfile); \ |
|
134 |
- FREESEC; \ |
|
135 |
- return CL_EUNLINK; \ |
|
136 |
- } \ |
|
137 |
- free(tempfile); \ |
|
138 |
- FREESEC; \ |
|
139 |
- found = 0; \ |
|
140 |
- upx_success = 1; \ |
|
141 |
- break; /* FSG ONLY! - scan raw data after upx block */ |
|
129 |
+ cli_dbgmsg(NAME": Successfully decompressed\n"); \ |
|
130 |
+ close(ndesc); \ |
|
131 |
+ if (cli_unlink(tempfile)) { \ |
|
132 |
+ free(exe_sections); \ |
|
133 |
+ free(tempfile); \ |
|
134 |
+ FREESEC; \ |
|
135 |
+ return CL_EUNLINK; \ |
|
136 |
+ } \ |
|
137 |
+ free(tempfile); \ |
|
138 |
+ FREESEC; \ |
|
139 |
+ found = 0; \ |
|
140 |
+ upx_success = 1; \ |
|
141 |
+ break; /* FSG ONLY! - scan raw data after upx block */ |
|
142 | 142 |
|
143 | 143 |
#define SPINCASE() \ |
144 | 144 |
case 2: \ |
145 |
- free(spinned); \ |
|
146 |
- close(ndesc); \ |
|
147 |
- if (cli_unlink(tempfile)) { \ |
|
148 |
- free(exe_sections); \ |
|
149 |
- free(tempfile); \ |
|
150 |
- return CL_EUNLINK; \ |
|
151 |
- } \ |
|
152 |
- cli_dbgmsg("PESpin: Size exceeded\n"); \ |
|
153 |
- free(tempfile); \ |
|
154 |
- break; \ |
|
145 |
+ free(spinned); \ |
|
146 |
+ close(ndesc); \ |
|
147 |
+ if (cli_unlink(tempfile)) { \ |
|
148 |
+ free(exe_sections); \ |
|
149 |
+ free(tempfile); \ |
|
150 |
+ return CL_EUNLINK; \ |
|
151 |
+ } \ |
|
152 |
+ cli_dbgmsg("PESpin: Size exceeded\n"); \ |
|
153 |
+ free(tempfile); \ |
|
154 |
+ break; \ |
|
155 | 155 |
|
156 | 156 |
#define CLI_UNPRESULTS_(NAME,FSGSTUFF,EXPR,GOOD,FREEME) \ |
157 | 157 |
switch(EXPR) { \ |
158 | 158 |
case GOOD: /* Unpacked and rebuilt */ \ |
159 |
- if(ctx->engine->keeptmp) \ |
|
160 |
- cli_dbgmsg(NAME": Unpacked and rebuilt executable saved in %s\n", tempfile); \ |
|
161 |
- else \ |
|
162 |
- cli_dbgmsg(NAME": Unpacked and rebuilt executable\n"); \ |
|
163 |
- cli_multifree FREEME; \ |
|
159 |
+ if(ctx->engine->keeptmp) \ |
|
160 |
+ cli_dbgmsg(NAME": Unpacked and rebuilt executable saved in %s\n", tempfile); \ |
|
161 |
+ else \ |
|
162 |
+ cli_dbgmsg(NAME": Unpacked and rebuilt executable\n"); \ |
|
163 |
+ cli_multifree FREEME; \ |
|
164 | 164 |
free(exe_sections); \ |
165 |
- lseek(ndesc, 0, SEEK_SET); \ |
|
166 |
- cli_dbgmsg("***** Scanning rebuilt PE file *****\n"); \ |
|
167 |
- SHA_OFF; \ |
|
168 |
- if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) { \ |
|
169 |
- close(ndesc); \ |
|
170 |
- CLI_TMPUNLK(); \ |
|
171 |
- free(tempfile); \ |
|
172 |
- SHA_RESET; \ |
|
173 |
- return CL_VIRUS; \ |
|
174 |
- } \ |
|
175 |
- SHA_RESET; \ |
|
176 |
- close(ndesc); \ |
|
177 |
- CLI_TMPUNLK(); \ |
|
178 |
- free(tempfile); \ |
|
179 |
- return CL_CLEAN; \ |
|
165 |
+ lseek(ndesc, 0, SEEK_SET); \ |
|
166 |
+ cli_dbgmsg("***** Scanning rebuilt PE file *****\n"); \ |
|
167 |
+ SHA_OFF; \ |
|
168 |
+ if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) { \ |
|
169 |
+ close(ndesc); \ |
|
170 |
+ CLI_TMPUNLK(); \ |
|
171 |
+ free(tempfile); \ |
|
172 |
+ SHA_RESET; \ |
|
173 |
+ return CL_VIRUS; \ |
|
174 |
+ } \ |
|
175 |
+ SHA_RESET; \ |
|
176 |
+ close(ndesc); \ |
|
177 |
+ CLI_TMPUNLK(); \ |
|
178 |
+ free(tempfile); \ |
|
179 |
+ return CL_CLEAN; \ |
|
180 | 180 |
\ |
181 | 181 |
FSGSTUFF; \ |
182 | 182 |
\ |
183 | 183 |
default: \ |
184 |
- cli_dbgmsg(NAME": Unpacking failed\n"); \ |
|
185 |
- close(ndesc); \ |
|
186 |
- if (cli_unlink(tempfile)) { \ |
|
187 |
- free(exe_sections); \ |
|
188 |
- free(tempfile); \ |
|
189 |
- cli_multifree FREEME; \ |
|
190 |
- return CL_EUNLINK; \ |
|
191 |
- } \ |
|
192 |
- cli_multifree FREEME; \ |
|
184 |
+ cli_dbgmsg(NAME": Unpacking failed\n"); \ |
|
185 |
+ close(ndesc); \ |
|
186 |
+ if (cli_unlink(tempfile)) { \ |
|
187 |
+ free(exe_sections); \ |
|
188 |
+ free(tempfile); \ |
|
189 |
+ cli_multifree FREEME; \ |
|
190 |
+ return CL_EUNLINK; \ |
|
191 |
+ } \ |
|
192 |
+ cli_multifree FREEME; \ |
|
193 | 193 |
free(tempfile); \ |
194 | 194 |
} |
195 | 195 |
|
... | ... |
@@ -227,7 +227,7 @@ static int versioninfo_cb(void *opaque, uint32_t type, uint32_t name, uint32_t l |
227 | 227 |
cli_dbgmsg("versioninfo_cb: type: %x, name: %x, lang: %x, rva: %x\n", type, name, lang, rva); |
228 | 228 |
vlist->rvas[vlist->count] = rva; |
229 | 229 |
if(++vlist->count == sizeof(vlist->rvas) / sizeof(vlist->rvas[0])) |
230 |
- return 1; |
|
230 |
+ return 1; |
|
231 | 231 |
return 0; |
232 | 232 |
} |
233 | 233 |
|
... | ... |
@@ -238,24 +238,25 @@ uint32_t cli_rawaddr(uint32_t rva, const struct cli_exe_section *shp, uint16_t n |
238 | 238 |
uint32_t ret; |
239 | 239 |
|
240 | 240 |
if (rva<hdr_size) { /* Out of section EP - mapped to imagebase+rva */ |
241 |
- if (rva >= fsize) { |
|
242 |
- *err=1; |
|
243 |
- return 0; |
|
244 |
- } |
|
241 |
+ if (rva >= fsize) { |
|
242 |
+ *err=1; |
|
243 |
+ return 0; |
|
244 |
+ } |
|
245 |
+ |
|
245 | 246 |
*err=0; |
246 |
- return rva; |
|
247 |
+ return rva; |
|
247 | 248 |
} |
248 | 249 |
|
249 | 250 |
for(i = nos-1; i >= 0; i--) { |
250 | 251 |
if(shp[i].rsz && shp[i].rva <= rva && shp[i].rsz > rva - shp[i].rva) { |
251 |
- found = 1; |
|
252 |
- break; |
|
253 |
- } |
|
252 |
+ found = 1; |
|
253 |
+ break; |
|
254 |
+ } |
|
254 | 255 |
} |
255 | 256 |
|
256 | 257 |
if(!found) { |
257 |
- *err = 1; |
|
258 |
- return 0; |
|
258 |
+ *err = 1; |
|
259 |
+ return 0; |
|
259 | 260 |
} |
260 | 261 |
|
261 | 262 |
ret = rva - shp[i].rva + shp[i].raw; |
... | ... |
@@ -263,61 +264,6 @@ uint32_t cli_rawaddr(uint32_t rva, const struct cli_exe_section *shp, uint16_t n |
263 | 263 |
return ret; |
264 | 264 |
} |
265 | 265 |
|
266 |
- |
|
267 |
-/* |
|
268 |
-static int cli_ddump(int desc, int offset, int size, const char *file) { |
|
269 |
- int pos, ndesc, bread, sum = 0; |
|
270 |
- char buff[FILEBUFF]; |
|
271 |
- |
|
272 |
- |
|
273 |
- cli_dbgmsg("in ddump()\n"); |
|
274 |
- |
|
275 |
- if((pos = lseek(desc, 0, SEEK_CUR)) == -1) { |
|
276 |
- cli_dbgmsg("Invalid descriptor\n"); |
|
277 |
- return -1; |
|
278 |
- } |
|
279 |
- |
|
280 |
- if(lseek(desc, offset, SEEK_SET) == -1) { |
|
281 |
- cli_dbgmsg("lseek() failed\n"); |
|
282 |
- lseek(desc, pos, SEEK_SET); |
|
283 |
- return -1; |
|
284 |
- } |
|
285 |
- |
|
286 |
- if((ndesc = open(file, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) { |
|
287 |
- cli_dbgmsg("Can't create file %s\n", file); |
|
288 |
- lseek(desc, pos, SEEK_SET); |
|
289 |
- return -1; |
|
290 |
- } |
|
291 |
- |
|
292 |
- while((bread = cli_readn(desc, buff, FILEBUFF)) > 0) { |
|
293 |
- if(sum + bread >= size) { |
|
294 |
- if(write(ndesc, buff, size - sum) == -1) { |
|
295 |
- cli_dbgmsg("Can't write to file\n"); |
|
296 |
- lseek(desc, pos, SEEK_SET); |
|
297 |
- close(ndesc); |
|
298 |
- cli_unlink(file); |
|
299 |
- return -1; |
|
300 |
- } |
|
301 |
- break; |
|
302 |
- } else { |
|
303 |
- if(write(ndesc, buff, bread) == -1) { |
|
304 |
- cli_dbgmsg("Can't write to file\n"); |
|
305 |
- lseek(desc, pos, SEEK_SET); |
|
306 |
- close(ndesc); |
|
307 |
- cli_unlink(file); |
|
308 |
- return -1; |
|
309 |
- } |
|
310 |
- } |
|
311 |
- sum += bread; |
|
312 |
- } |
|
313 |
- |
|
314 |
- close(ndesc); |
|
315 |
- lseek(desc, pos, SEEK_SET); |
|
316 |
- return 0; |
|
317 |
-} |
|
318 |
-*/ |
|
319 |
- |
|
320 |
- |
|
321 | 266 |
/* |
322 | 267 |
void findres(uint32_t by_type, uint32_t by_name, uint32_t res_rva, cli_ctx *ctx, struct cli_exe_section *exe_sections, uint16_t nsections, uint32_t hdr_size, int (*cb)(void *, uint32_t, uint32_t, uint32_t, uint32_t), void *opaque) |
323 | 268 |
callback based res lookup |
... | ... |
@@ -2885,91 +2831,94 @@ int cli_scanpe(cli_ctx *ctx) |
2885 | 2885 |
|
2886 | 2886 |
int cli_peheader(fmap_t *map, struct cli_exe_info *peinfo) |
2887 | 2887 |
{ |
2888 |
- uint16_t e_magic; /* DOS signature ("MZ") */ |
|
2889 |
- uint32_t e_lfanew; /* address of new exe header */ |
|
2890 |
- /* Obsolete - see below |
|
2891 |
- uint32_t min = 0, max = 0; |
|
2892 |
- */ |
|
2893 |
- struct pe_image_file_hdr file_hdr; |
|
2894 |
- union { |
|
2895 |
- struct pe_image_optional_hdr64 opt64; |
|
2896 |
- struct pe_image_optional_hdr32 opt32; |
|
2897 |
- } pe_opt; |
|
2898 |
- struct pe_image_section_hdr *section_hdr; |
|
2899 |
- unsigned int i; |
|
2900 |
- unsigned int err, pe_plus = 0; |
|
2901 |
- uint32_t valign, falign, hdr_size; |
|
2902 |
- size_t fsize; |
|
2903 |
- ssize_t at; |
|
2904 |
- struct pe_image_data_dir *dirs; |
|
2888 |
+ uint16_t e_magic; /* DOS signature ("MZ") */ |
|
2889 |
+ uint32_t e_lfanew; /* address of new exe header */ |
|
2890 |
+ /* Obsolete - see below |
|
2891 |
+ uint32_t min = 0, max = 0; |
|
2892 |
+ */ |
|
2893 |
+ struct pe_image_file_hdr file_hdr; |
|
2894 |
+ union { |
|
2895 |
+ struct pe_image_optional_hdr64 opt64; |
|
2896 |
+ struct pe_image_optional_hdr32 opt32; |
|
2897 |
+ } pe_opt; |
|
2898 |
+ struct pe_image_section_hdr *section_hdr; |
|
2899 |
+ unsigned int i; |
|
2900 |
+ unsigned int err, pe_plus = 0; |
|
2901 |
+ uint32_t valign, falign, hdr_size; |
|
2902 |
+ size_t fsize; |
|
2903 |
+ ssize_t at; |
|
2904 |
+ struct pe_image_data_dir *dirs; |
|
2905 | 2905 |
|
2906 | 2906 |
cli_dbgmsg("in cli_peheader\n"); |
2907 | 2907 |
|
2908 | 2908 |
fsize = map->len - peinfo->offset; |
2909 | 2909 |
if(fmap_readn(map, &e_magic, peinfo->offset, sizeof(e_magic)) != sizeof(e_magic)) { |
2910 |
- cli_dbgmsg("Can't read DOS signature\n"); |
|
2911 |
- return -1; |
|
2910 |
+ cli_dbgmsg("Can't read DOS signature\n"); |
|
2911 |
+ return -1; |
|
2912 | 2912 |
} |
2913 | 2913 |
|
2914 | 2914 |
if(EC16(e_magic) != PE_IMAGE_DOS_SIGNATURE && EC16(e_magic) != PE_IMAGE_DOS_SIGNATURE_OLD) { |
2915 |
- cli_dbgmsg("Invalid DOS signature\n"); |
|
2916 |
- return -1; |
|
2915 |
+ cli_dbgmsg("Invalid DOS signature\n"); |
|
2916 |
+ return -1; |
|
2917 | 2917 |
} |
2918 | 2918 |
|
2919 | 2919 |
if(fmap_readn(map, &e_lfanew, peinfo->offset + 58 + sizeof(e_magic), sizeof(e_lfanew)) != sizeof(e_lfanew)) { |
2920 |
- /* truncated header? */ |
|
2921 |
- return -1; |
|
2920 |
+ /* truncated header? */ |
|
2921 |
+ return -1; |
|
2922 | 2922 |
} |
2923 | 2923 |
|
2924 | 2924 |
e_lfanew = EC32(e_lfanew); |
2925 | 2925 |
if(!e_lfanew) { |
2926 |
- cli_dbgmsg("Not a PE file\n"); |
|
2927 |
- return -1; |
|
2926 |
+ cli_dbgmsg("Not a PE file\n"); |
|
2927 |
+ return -1; |
|
2928 | 2928 |
} |
2929 | 2929 |
|
2930 | 2930 |
if(fmap_readn(map, &file_hdr, peinfo->offset + e_lfanew, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) { |
2931 |
- /* bad information in e_lfanew - probably not a PE file */ |
|
2932 |
- cli_dbgmsg("Can't read file header\n"); |
|
2933 |
- return -1; |
|
2931 |
+ /* bad information in e_lfanew - probably not a PE file */ |
|
2932 |
+ cli_dbgmsg("Can't read file header\n"); |
|
2933 |
+ return -1; |
|
2934 | 2934 |
} |
2935 | 2935 |
|
2936 | 2936 |
if(EC32(file_hdr.Magic) != PE_IMAGE_NT_SIGNATURE) { |
2937 |
- cli_dbgmsg("Invalid PE signature (probably NE file)\n"); |
|
2938 |
- return -1; |
|
2937 |
+ cli_dbgmsg("Invalid PE signature (probably NE file)\n"); |
|
2938 |
+ return -1; |
|
2939 | 2939 |
} |
2940 | 2940 |
|
2941 | 2941 |
if ( (peinfo->nsections = EC16(file_hdr.NumberOfSections)) < 1 || peinfo->nsections > 96 ) return -1; |
2942 | 2942 |
|
2943 | 2943 |
if (EC16(file_hdr.SizeOfOptionalHeader) < sizeof(struct pe_image_optional_hdr32)) { |
2944 | 2944 |
cli_dbgmsg("SizeOfOptionalHeader too small\n"); |
2945 |
- return -1; |
|
2945 |
+ return -1; |
|
2946 | 2946 |
} |
2947 | 2947 |
|
2948 | 2948 |
at = peinfo->offset + e_lfanew + sizeof(struct pe_image_file_hdr); |
2949 | 2949 |
if(fmap_readn(map, &optional_hdr32, at, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) { |
2950 | 2950 |
cli_dbgmsg("Can't read optional file header\n"); |
2951 |
- return -1; |
|
2951 |
+ return -1; |
|
2952 | 2952 |
} |
2953 | 2953 |
at += sizeof(struct pe_image_optional_hdr32); |
2954 | 2954 |
|
2955 | 2955 |
if(EC16(optional_hdr64.Magic)==PE32P_SIGNATURE) { /* PE+ */ |
2956 | 2956 |
if(EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr64)) { |
2957 |
- cli_dbgmsg("Incorrect SizeOfOptionalHeader for PE32+\n"); |
|
2958 |
- return -1; |
|
2959 |
- } |
|
2960 |
- if(fmap_readn(map, &optional_hdr32 + 1, at, sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) { |
|
2961 |
- cli_dbgmsg("Can't read optional file header\n"); |
|
2962 |
- return -1; |
|
2963 |
- } |
|
2964 |
- at += sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32); |
|
2965 |
- hdr_size = EC32(optional_hdr64.SizeOfHeaders); |
|
2966 |
- pe_plus=1; |
|
2957 |
+ cli_dbgmsg("Incorrect SizeOfOptionalHeader for PE32+\n"); |
|
2958 |
+ return -1; |
|
2959 |
+ } |
|
2960 |
+ |
|
2961 |
+ if(fmap_readn(map, &optional_hdr32 + 1, at, sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) { |
|
2962 |
+ cli_dbgmsg("Can't read optional file header\n"); |
|
2963 |
+ return -1; |
|
2964 |
+ } |
|
2965 |
+ |
|
2966 |
+ at += sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32); |
|
2967 |
+ hdr_size = EC32(optional_hdr64.SizeOfHeaders); |
|
2968 |
+ pe_plus=1; |
|
2967 | 2969 |
} else { /* PE */ |
2968 |
- if (EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr32)) { |
|
2969 |
- /* Seek to the end of the long header */ |
|
2970 |
- at += EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32); |
|
2971 |
- } |
|
2972 |
- hdr_size = EC32(optional_hdr32.SizeOfHeaders); |
|
2970 |
+ if (EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr32)) { |
|
2971 |
+ /* Seek to the end of the long header */ |
|
2972 |
+ at += EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32); |
|
2973 |
+ } |
|
2974 |
+ |
|
2975 |
+ hdr_size = EC32(optional_hdr32.SizeOfHeaders); |
|
2973 | 2976 |
} |
2974 | 2977 |
|
2975 | 2978 |
valign = (pe_plus)?EC32(optional_hdr64.SectionAlignment):EC32(optional_hdr32.SectionAlignment); |
... | ... |
@@ -2980,249 +2929,253 @@ int cli_peheader(fmap_t *map, struct cli_exe_info *peinfo) |
2980 | 2980 |
peinfo->section = (struct cli_exe_section *) cli_calloc(peinfo->nsections, sizeof(struct cli_exe_section)); |
2981 | 2981 |
|
2982 | 2982 |
if(!peinfo->section) { |
2983 |
- cli_dbgmsg("Can't allocate memory for section headers\n"); |
|
2984 |
- return -1; |
|
2983 |
+ cli_dbgmsg("Can't allocate memory for section headers\n"); |
|
2984 |
+ return -1; |
|
2985 | 2985 |
} |
2986 | 2986 |
|
2987 | 2987 |
section_hdr = (struct pe_image_section_hdr *) cli_calloc(peinfo->nsections, sizeof(struct pe_image_section_hdr)); |
2988 | 2988 |
|
2989 | 2989 |
if(!section_hdr) { |
2990 |
- cli_dbgmsg("Can't allocate memory for section headers\n"); |
|
2991 |
- free(peinfo->section); |
|
2992 |
- peinfo->section = NULL; |
|
2993 |
- return -1; |
|
2990 |
+ cli_dbgmsg("Can't allocate memory for section headers\n"); |
|
2991 |
+ free(peinfo->section); |
|
2992 |
+ peinfo->section = NULL; |
|
2993 |
+ return -1; |
|
2994 | 2994 |
} |
2995 | 2995 |
|
2996 | 2996 |
if(fmap_readn(map, section_hdr, at, peinfo->nsections * sizeof(struct pe_image_section_hdr)) != peinfo->nsections * sizeof(struct pe_image_section_hdr)) { |
2997 | 2997 |
cli_dbgmsg("Can't read section header\n"); |
2998 |
- cli_dbgmsg("Possibly broken PE file\n"); |
|
2999 |
- free(section_hdr); |
|
3000 |
- free(peinfo->section); |
|
3001 |
- peinfo->section = NULL; |
|
3002 |
- return -1; |
|
2998 |
+ cli_dbgmsg("Possibly broken PE file\n"); |
|
2999 |
+ free(section_hdr); |
|
3000 |
+ free(peinfo->section); |
|
3001 |
+ peinfo->section = NULL; |
|
3002 |
+ return -1; |
|
3003 | 3003 |
} |
3004 | 3004 |
at += sizeof(struct pe_image_section_hdr)*peinfo->nsections; |
3005 | 3005 |
|
3006 | 3006 |
for(i = 0; falign!=0x200 && i<peinfo->nsections; i++) { |
3007 |
- /* file alignment fallback mode - blah */ |
|
3008 |
- if (falign && section_hdr[i].SizeOfRawData && EC32(section_hdr[i].PointerToRawData)%falign && !(EC32(section_hdr[i].PointerToRawData)%0x200)) { |
|
3009 |
- falign = 0x200; |
|
3010 |
- } |
|
3007 |
+ /* file alignment fallback mode - blah */ |
|
3008 |
+ if (falign && section_hdr[i].SizeOfRawData && EC32(section_hdr[i].PointerToRawData)%falign && !(EC32(section_hdr[i].PointerToRawData)%0x200)) { |
|
3009 |
+ falign = 0x200; |
|
3010 |
+ } |
|
3011 | 3011 |
} |
3012 | 3012 |
|
3013 | 3013 |
for(i = 0; i < peinfo->nsections; i++) { |
3014 | 3014 |
peinfo->section[i].rva = PEALIGN(EC32(section_hdr[i].VirtualAddress), valign); |
3015 |
- peinfo->section[i].vsz = PESALIGN(EC32(section_hdr[i].VirtualSize), valign); |
|
3016 |
- peinfo->section[i].raw = PEALIGN(EC32(section_hdr[i].PointerToRawData), falign); |
|
3017 |
- peinfo->section[i].rsz = PESALIGN(EC32(section_hdr[i].SizeOfRawData), falign); |
|
3015 |
+ peinfo->section[i].vsz = PESALIGN(EC32(section_hdr[i].VirtualSize), valign); |
|
3016 |
+ peinfo->section[i].raw = PEALIGN(EC32(section_hdr[i].PointerToRawData), falign); |
|
3017 |
+ peinfo->section[i].rsz = PESALIGN(EC32(section_hdr[i].SizeOfRawData), falign); |
|
3018 | 3018 |
|
3019 |
- if (!peinfo->section[i].vsz && peinfo->section[i].rsz) |
|
3020 |
- peinfo->section[i].vsz=PESALIGN(EC32(section_hdr[i].SizeOfRawData), valign); |
|
3019 |
+ if (!peinfo->section[i].vsz && peinfo->section[i].rsz) |
|
3020 |
+ peinfo->section[i].vsz=PESALIGN(EC32(section_hdr[i].SizeOfRawData), valign); |
|
3021 | 3021 |
|
3022 |
- if (peinfo->section[i].rsz && !CLI_ISCONTAINED(0, (uint32_t) fsize, peinfo->section[i].raw, peinfo->section[i].rsz)) |
|
3023 |
- peinfo->section[i].rsz = (fsize - peinfo->section[i].raw)*(fsize>peinfo->section[i].raw); |
|
3022 |
+ if (peinfo->section[i].rsz && !CLI_ISCONTAINED(0, (uint32_t) fsize, peinfo->section[i].raw, peinfo->section[i].rsz)) |
|
3023 |
+ peinfo->section[i].rsz = (fsize - peinfo->section[i].raw)*(fsize>peinfo->section[i].raw); |
|
3024 | 3024 |
} |
3025 | 3025 |
|
3026 | 3026 |
if(pe_plus) { |
3027 |
- peinfo->ep = EC32(optional_hdr64.AddressOfEntryPoint); |
|
3028 |
- dirs = optional_hdr64.DataDirectory; |
|
3027 |
+ peinfo->ep = EC32(optional_hdr64.AddressOfEntryPoint); |
|
3028 |
+ dirs = optional_hdr64.DataDirectory; |
|
3029 | 3029 |
} else { |
3030 |
- peinfo->ep = EC32(optional_hdr32.AddressOfEntryPoint); |
|
3031 |
- dirs = optional_hdr32.DataDirectory; |
|
3030 |
+ peinfo->ep = EC32(optional_hdr32.AddressOfEntryPoint); |
|
3031 |
+ dirs = optional_hdr32.DataDirectory; |
|
3032 | 3032 |
} |
3033 | 3033 |
|
3034 | 3034 |
if(!(peinfo->ep = cli_rawaddr(peinfo->ep, peinfo->section, peinfo->nsections, &err, fsize, hdr_size)) && err) { |
3035 |
- cli_dbgmsg("Broken PE file\n"); |
|
3036 |
- free(section_hdr); |
|
3037 |
- free(peinfo->section); |
|
3038 |
- peinfo->section = NULL; |
|
3039 |
- return -1; |
|
3035 |
+ cli_dbgmsg("Broken PE file\n"); |
|
3036 |
+ free(section_hdr); |
|
3037 |
+ free(peinfo->section); |
|
3038 |
+ peinfo->section = NULL; |
|
3039 |
+ return -1; |
|
3040 | 3040 |
} |
3041 | 3041 |
|
3042 | 3042 |
if(EC16(file_hdr.Characteristics) & 0x2000 || !dirs[2].Size) |
3043 |
- peinfo->res_addr = 0; |
|
3043 |
+ peinfo->res_addr = 0; |
|
3044 | 3044 |
else |
3045 |
- peinfo->res_addr = EC32(dirs[2].VirtualAddress); |
|
3045 |
+ peinfo->res_addr = EC32(dirs[2].VirtualAddress); |
|
3046 | 3046 |
|
3047 | 3047 |
while(dirs[2].Size) { |
3048 |
- struct vinfo_list vlist; |
|
3049 |
- const uint8_t *vptr, *baseptr; |
|
3050 |
- uint32_t rva, res_sz; |
|
3051 |
- |
|
3052 |
- memset(&vlist, 0, sizeof(vlist)); |
|
3053 |
- findres(0x10, 0xffffffff, EC32(dirs[2].VirtualAddress), map, peinfo->section, peinfo->nsections, hdr_size, versioninfo_cb, &vlist); |
|
3054 |
- if(!vlist.count) break; /* No version_information */ |
|
3055 |
- if(cli_hashset_init(&peinfo->vinfo, 32, 80)) { |
|
3056 |
- cli_errmsg("cli_peheader: Unable to init vinfo hashset\n"); |
|
3057 |
- free(section_hdr); |
|
3058 |
- free(peinfo->section); |
|
3059 |
- peinfo->section = NULL; |
|
3060 |
- return -1; |
|
3061 |
- } |
|
3048 |
+ struct vinfo_list vlist; |
|
3049 |
+ const uint8_t *vptr, *baseptr; |
|
3050 |
+ uint32_t rva, res_sz; |
|
3062 | 3051 |
|
3063 |
- err = 0; |
|
3064 |
- for(i=0; i<vlist.count; i++) { /* enum all version_information res - RESUMABLE */ |
|
3065 |
- cli_dbgmsg("cli_peheader: parsing version info @ rva %x (%u/%u)\n", vlist.rvas[i], i+1, vlist.count); |
|
3066 |
- rva = cli_rawaddr(vlist.rvas[i], peinfo->section, peinfo->nsections, &err, fsize, hdr_size); |
|
3067 |
- if(err) |
|
3068 |
- continue; |
|
3052 |
+ memset(&vlist, 0, sizeof(vlist)); |
|
3053 |
+ findres(0x10, 0xffffffff, EC32(dirs[2].VirtualAddress), map, peinfo->section, peinfo->nsections, hdr_size, versioninfo_cb, &vlist); |
|
3054 |
+ if(!vlist.count) |
|
3055 |
+ break; /* No version_information */ |
|
3069 | 3056 |
|
3070 |
- if(!(vptr = fmap_need_off_once(map, rva, 16))) |
|
3071 |
- continue; |
|
3057 |
+ if(cli_hashset_init(&peinfo->vinfo, 32, 80)) { |
|
3058 |
+ cli_errmsg("cli_peheader: Unable to init vinfo hashset\n"); |
|
3059 |
+ free(section_hdr); |
|
3060 |
+ free(peinfo->section); |
|
3061 |
+ peinfo->section = NULL; |
|
3062 |
+ return -1; |
|
3063 |
+ } |
|
3072 | 3064 |
|
3073 |
- baseptr = vptr - rva; |
|
3074 |
- /* parse resource */ |
|
3075 |
- rva = cli_readint32(vptr); /* ptr to version_info */ |
|
3076 |
- res_sz = cli_readint32(vptr+4); /* sizeof(resource) */ |
|
3077 |
- rva = cli_rawaddr(rva, peinfo->section, peinfo->nsections, &err, fsize, hdr_size); |
|
3078 |
- if(err) |
|
3079 |
- continue; |
|
3080 |
- if(!(vptr = fmap_need_off_once(map, rva, res_sz))) |
|
3081 |
- continue; |
|
3082 |
- |
|
3083 |
- while(res_sz>4) { /* look for version_info - NOT RESUMABLE (expecting exactly one versioninfo) */ |
|
3084 |
- uint32_t vinfo_sz, vinfo_val_sz, got_varfileinfo = 0; |
|
3085 |
- |
|
3086 |
- vinfo_sz = vinfo_val_sz = cli_readint32(vptr); |
|
3087 |
- vinfo_sz &= 0xffff; |
|
3088 |
- if(vinfo_sz > res_sz) |
|
3089 |
- break; /* the content is larger than the container */ |
|
3090 |
- |
|
3091 |
- vinfo_val_sz >>= 16; |
|
3092 |
- if(vinfo_sz <= 6 + 0x20 + 2 + 0x34 || |
|
3093 |
- vinfo_val_sz != 0x34 || |
|
3094 |
- memcmp(vptr+6, "V\0S\0_\0V\0E\0R\0S\0I\0O\0N\0_\0I\0N\0F\0O\0\0\0", 0x20) || |
|
3095 |
- (unsigned int)cli_readint32(vptr + 0x28) != 0xfeef04bd) { |
|
3096 |
- /* - there should be enough room for the header(6), the key "VS_VERSION_INFO"(20), the padding(2) and the value(34) |
|
3097 |
- * - the value should be sizeof(fixedfileinfo) |
|
3098 |
- * - the key should match |
|
3099 |
- * - there should be some proper magic for fixedfileinfo */ |
|
3100 |
- break; /* there's no point in looking further */ |
|
3101 |
- } |
|
3065 |
+ err = 0; |
|
3066 |
+ for(i=0; i<vlist.count; i++) { /* enum all version_information res - RESUMABLE */ |
|
3067 |
+ cli_dbgmsg("cli_peheader: parsing version info @ rva %x (%u/%u)\n", vlist.rvas[i], i+1, vlist.count); |
|
3068 |
+ rva = cli_rawaddr(vlist.rvas[i], peinfo->section, peinfo->nsections, &err, fsize, hdr_size); |
|
3069 |
+ if(err) |
|
3070 |
+ continue; |
|
3102 | 3071 |
|
3103 |
- /* move to the end of fixedfileinfo where the child elements are located */ |
|
3104 |
- vptr += 6 + 0x20 + 2 + 0x34; |
|
3105 |
- vinfo_sz -= 6 + 0x20 + 2 + 0x34; |
|
3072 |
+ if(!(vptr = fmap_need_off_once(map, rva, 16))) |
|
3073 |
+ continue; |
|
3106 | 3074 |
|
3107 |
- while(vinfo_sz > 6) { /* look for stringfileinfo - NOT RESUMABLE (expecting at most one stringfileinfo) */ |
|
3108 |
- uint32_t sfi_sz = cli_readint32(vptr) & 0xffff; |
|
3075 |
+ baseptr = vptr - rva; |
|
3076 |
+ /* parse resource */ |
|
3077 |
+ rva = cli_readint32(vptr); /* ptr to version_info */ |
|
3078 |
+ res_sz = cli_readint32(vptr+4); /* sizeof(resource) */ |
|
3079 |
+ rva = cli_rawaddr(rva, peinfo->section, peinfo->nsections, &err, fsize, hdr_size); |
|
3080 |
+ if(err) |
|
3081 |
+ continue; |
|
3082 |
+ if(!(vptr = fmap_need_off_once(map, rva, res_sz))) |
|
3083 |
+ continue; |
|
3084 |
+ |
|
3085 |
+ while(res_sz>4) { /* look for version_info - NOT RESUMABLE (expecting exactly one versioninfo) */ |
|
3086 |
+ uint32_t vinfo_sz, vinfo_val_sz, got_varfileinfo = 0; |
|
3087 |
+ |
|
3088 |
+ vinfo_sz = vinfo_val_sz = cli_readint32(vptr); |
|
3089 |
+ vinfo_sz &= 0xffff; |
|
3090 |
+ if(vinfo_sz > res_sz) |
|
3091 |
+ break; /* the content is larger than the container */ |
|
3092 |
+ |
|
3093 |
+ vinfo_val_sz >>= 16; |
|
3094 |
+ if(vinfo_sz <= 6 + 0x20 + 2 + 0x34 || |
|
3095 |
+ vinfo_val_sz != 0x34 || |
|
3096 |
+ memcmp(vptr+6, "V\0S\0_\0V\0E\0R\0S\0I\0O\0N\0_\0I\0N\0F\0O\0\0\0", 0x20) || |
|
3097 |
+ (unsigned int)cli_readint32(vptr + 0x28) != 0xfeef04bd) { |
|
3098 |
+ /* - there should be enough room for the header(6), the key "VS_VERSION_INFO"(20), the padding(2) and the value(34) |
|
3099 |
+ * - the value should be sizeof(fixedfileinfo) |
|
3100 |
+ * - the key should match |
|
3101 |
+ * - there should be some proper magic for fixedfileinfo */ |
|
3102 |
+ break; /* there's no point in looking further */ |
|
3103 |
+ } |
|
3109 | 3104 |
|
3110 |
- if(sfi_sz > vinfo_sz) |
|
3111 |
- break; /* the content is larger than the container */ |
|
3105 |
+ /* move to the end of fixedfileinfo where the child elements are located */ |
|
3106 |
+ vptr += 6 + 0x20 + 2 + 0x34; |
|
3107 |
+ vinfo_sz -= 6 + 0x20 + 2 + 0x34; |
|
3112 | 3108 |
|
3113 |
- if(!got_varfileinfo && sfi_sz > 6 + 0x18 && !memcmp(vptr+6, "V\0a\0r\0F\0i\0l\0e\0I\0n\0f\0o\0\0\0", 0x18)) { |
|
3114 |
- /* skip varfileinfo as it sometimes appear before stringtableinfo */ |
|
3115 |
- vptr += sfi_sz; |
|
3116 |
- vinfo_sz -= sfi_sz; |
|
3117 |
- got_varfileinfo = 1; |
|
3118 |
- continue; |
|
3119 |
- } |
|
3109 |
+ while(vinfo_sz > 6) { /* look for stringfileinfo - NOT RESUMABLE (expecting at most one stringfileinfo) */ |
|
3110 |
+ uint32_t sfi_sz = cli_readint32(vptr) & 0xffff; |
|
3120 | 3111 |
|
3121 |
- if(sfi_sz <= 6 + 0x1e || memcmp(vptr+6, "S\0t\0r\0i\0n\0g\0F\0i\0l\0e\0I\0n\0f\0o\0\0\0", 0x1e)) { |
|
3122 |
- /* - there should be enough room for the header(6) and the key "StringFileInfo"(1e) |
|
3123 |
- * - the key should match */ |
|
3124 |
- break; /* this is an implicit hard fail: parent is not resumable */ |
|
3125 |
- } |
|
3112 |
+ if(sfi_sz > vinfo_sz) |
|
3113 |
+ break; /* the content is larger than the container */ |
|
3126 | 3114 |
|
3127 |
- /* move to the end of stringfileinfo where the child elements are located */ |
|
3128 |
- vptr += 6 + 0x1e; |
|
3129 |
- sfi_sz -= 6 + 0x1e; |
|
3115 |
+ if(!got_varfileinfo && sfi_sz > 6 + 0x18 && !memcmp(vptr+6, "V\0a\0r\0F\0i\0l\0e\0I\0n\0f\0o\0\0\0", 0x18)) { |
|
3116 |
+ /* skip varfileinfo as it sometimes appear before stringtableinfo */ |
|
3117 |
+ vptr += sfi_sz; |
|
3118 |
+ vinfo_sz -= sfi_sz; |
|
3119 |
+ got_varfileinfo = 1; |
|
3120 |
+ continue; |
|
3121 |
+ } |
|
3130 | 3122 |
|
3131 |
- while(sfi_sz > 6) { /* enum all stringtables - RESUMABLE */ |
|
3132 |
- uint32_t st_sz = cli_readint32(vptr) & 0xffff; |
|
3133 |
- const uint8_t *next_vptr = vptr + st_sz; |
|
3134 |
- uint32_t next_sfi_sz = sfi_sz - st_sz; |
|
3123 |
+ if(sfi_sz <= 6 + 0x1e || memcmp(vptr+6, "S\0t\0r\0i\0n\0g\0F\0i\0l\0e\0I\0n\0f\0o\0\0\0", 0x1e)) { |
|
3124 |
+ /* - there should be enough room for the header(6) and the key "StringFileInfo"(1e) |
|
3125 |
+ * - the key should match */ |
|
3126 |
+ break; /* this is an implicit hard fail: parent is not resumable */ |
|
3127 |
+ } |
|
3135 | 3128 |
|
3136 |
- if(st_sz > sfi_sz || st_sz <= 24) { |
|
3137 |
- /* - the content is larger than the container |
|
3138 |
- - there's no room for a stringtables (headers(6) + key(16) + padding(2)) */ |
|
3139 |
- break; /* this is an implicit hard fail: parent is not resumable */ |
|
3140 |
- } |
|
3129 |
+ /* move to the end of stringfileinfo where the child elements are located */ |
|
3130 |
+ vptr += 6 + 0x1e; |
|
3131 |
+ sfi_sz -= 6 + 0x1e; |
|
3141 | 3132 |
|
3142 |
- /* move to the end of stringtable where the child elements are located */ |
|
3143 |
- vptr += 24; |
|
3144 |
- st_sz -= 24; |
|
3145 |
- |
|
3146 |
- while(st_sz > 6) { /* enum all strings - RESUMABLE */ |
|
3147 |
- uint32_t s_sz, s_key_sz, s_val_sz; |
|
3148 |
- |
|
3149 |
- s_sz = (cli_readint32(vptr) & 0xffff) + 3; |
|
3150 |
- s_sz &= ~3; |
|
3151 |
- if(s_sz > st_sz || s_sz <= 6 + 2 + 8) { |
|
3152 |
- /* - the content is larger than the container |
|
3153 |
- * - there's no room for a minimal string |
|
3154 |
- * - there's no room for the value */ |
|
3155 |
- st_sz = 0; |
|
3156 |
- sfi_sz = 0; |
|
3157 |
- break; /* force a hard fail */ |
|
3158 |
- } |
|
3159 |
- |
|
3160 |
- /* ~wcstrlen(key) */ |
|
3161 |
- for(s_key_sz = 6; s_key_sz+1 < s_sz; s_key_sz += 2) { |
|
3162 |
- if(vptr[s_key_sz] || vptr[s_key_sz+1]) continue; |
|
3163 |
- s_key_sz += 2; |
|
3164 |
- break; |
|
3165 |
- } |
|
3166 |
- |
|
3167 |
- s_key_sz += 3; |
|
3168 |
- s_key_sz &= ~3; |
|
3169 |
- |
|
3170 |
- if(s_key_sz >= s_sz) { |
|
3171 |
- /* key overflow */ |
|
3172 |
- vptr += s_sz; |
|
3173 |
- st_sz -= s_sz; |
|
3174 |
- continue; |
|
3175 |
- } |
|
3176 |
- |
|
3177 |
- s_val_sz = s_sz - s_key_sz; |
|
3178 |
- s_key_sz -= 6; |
|
3179 |
- |
|
3180 |
- if(s_val_sz <= 2) { |
|
3181 |
- /* skip unset value */ |
|
3182 |
- vptr += s_sz; |
|
3183 |
- st_sz -= s_sz; |
|
3184 |
- continue; |
|
3185 |
- } |
|
3186 |
- |
|
3187 |
- if(cli_hashset_addkey(&peinfo->vinfo, (uint32_t)(vptr - baseptr + 6))) { |
|
3188 |
- cli_errmsg("cli_peheader: Unable to add rva to vinfo hashset\n"); |
|
3189 |
- cli_hashset_destroy(&peinfo->vinfo); |
|
3190 |
- free(section_hdr); |
|
3191 |
- free(peinfo->section); |
|
3192 |
- peinfo->section = NULL; |
|
3193 |
- return -1; |
|
3194 |
- } |
|
3195 |
- |
|
3196 |
- if(cli_debug_flag) { |
|
3197 |
- char *k, *v, *s; |
|
3198 |
- |
|
3199 |
- /* FIXME: skip too long strings */ |
|
3200 |
- k = cli_utf16toascii((const char*)vptr + 6, s_key_sz); |
|
3201 |
- if(k) { |
|
3202 |
- v = cli_utf16toascii((const char*)vptr + s_key_sz + 6, s_val_sz); |
|
3203 |
- if(v) { |
|
3204 |
- s = cli_str2hex((const char*)vptr + 6, s_key_sz + s_val_sz - 6); |
|
3205 |
- if(s) { |
|
3206 |
- cli_dbgmsg("VersionInfo (%x): '%s'='%s' - VI:%s\n", (uint32_t)(vptr - baseptr + 6), k, v, s); |
|
3207 |
- free(s); |
|
3208 |
- } |
|
3209 |
- free(v); |
|
3210 |
- } |
|
3211 |
- free(k); |
|
3212 |
- } |
|
3213 |
- } |
|
3214 |
- vptr += s_sz; |
|
3215 |
- st_sz -= s_sz; |
|
3216 |
- } /* enum all strings - RESUMABLE */ |
|
3217 |
- vptr = next_vptr; |
|
3218 |
- sfi_sz = next_sfi_sz * (sfi_sz != 0); |
|
3219 |
- } /* enum all stringtables - RESUMABLE */ |
|
3220 |
- break; |
|
3221 |
- } /* look for stringfileinfo - NOT RESUMABLE */ |
|
3222 |
- break; |
|
3223 |
- } /* look for version_info - NOT RESUMABLE */ |
|
3224 |
- } /* enum all version_information res - RESUMABLE */ |
|
3225 |
- break; |
|
3133 |
+ while(sfi_sz > 6) { /* enum all stringtables - RESUMABLE */ |
|
3134 |
+ uint32_t st_sz = cli_readint32(vptr) & 0xffff; |
|
3135 |
+ const uint8_t *next_vptr = vptr + st_sz; |
|
3136 |
+ uint32_t next_sfi_sz = sfi_sz - st_sz; |
|
3137 |
+ |
|
3138 |
+ if(st_sz > sfi_sz || st_sz <= 24) { |
|
3139 |
+ /* - the content is larger than the container |
|
3140 |
+ - there's no room for a stringtables (headers(6) + key(16) + padding(2)) */ |
|
3141 |
+ break; /* this is an implicit hard fail: parent is not resumable */ |
|
3142 |
+ } |
|
3143 |
+ |
|
3144 |
+ /* move to the end of stringtable where the child elements are located */ |
|
3145 |
+ vptr += 24; |
|
3146 |
+ st_sz -= 24; |
|
3147 |
+ |
|
3148 |
+ while(st_sz > 6) { /* enum all strings - RESUMABLE */ |
|
3149 |
+ uint32_t s_sz, s_key_sz, s_val_sz; |
|
3150 |
+ |
|
3151 |
+ s_sz = (cli_readint32(vptr) & 0xffff) + 3; |
|
3152 |
+ s_sz &= ~3; |
|
3153 |
+ if(s_sz > st_sz || s_sz <= 6 + 2 + 8) { |
|
3154 |
+ /* - the content is larger than the container |
|
3155 |
+ * - there's no room for a minimal string |
|
3156 |
+ * - there's no room for the value */ |
|
3157 |
+ st_sz = 0; |
|
3158 |
+ sfi_sz = 0; |
|
3159 |
+ break; /* force a hard fail */ |
|
3160 |
+ } |
|
3161 |
+ |
|
3162 |
+ /* ~wcstrlen(key) */ |
|
3163 |
+ for(s_key_sz = 6; s_key_sz+1 < s_sz; s_key_sz += 2) { |
|
3164 |
+ if(vptr[s_key_sz] || vptr[s_key_sz+1]) |
|
3165 |
+ continue; |
|
3166 |
+ |
|
3167 |
+ s_key_sz += 2; |
|
3168 |
+ break; |
|
3169 |
+ } |
|
3170 |
+ |
|
3171 |
+ s_key_sz += 3; |
|
3172 |
+ s_key_sz &= ~3; |
|
3173 |
+ |
|
3174 |
+ if(s_key_sz >= s_sz) { |
|
3175 |
+ /* key overflow */ |
|
3176 |
+ vptr += s_sz; |
|
3177 |
+ st_sz -= s_sz; |
|
3178 |
+ continue; |
|
3179 |
+ } |
|
3180 |
+ |
|
3181 |
+ s_val_sz = s_sz - s_key_sz; |
|
3182 |
+ s_key_sz -= 6; |
|
3183 |
+ |
|
3184 |
+ if(s_val_sz <= 2) { |
|
3185 |
+ /* skip unset value */ |
|
3186 |
+ vptr += s_sz; |
|
3187 |
+ st_sz -= s_sz; |
|
3188 |
+ continue; |
|
3189 |
+ } |
|
3190 |
+ |
|
3191 |
+ if(cli_hashset_addkey(&peinfo->vinfo, (uint32_t)(vptr - baseptr + 6))) { |
|
3192 |
+ cli_errmsg("cli_peheader: Unable to add rva to vinfo hashset\n"); |
|
3193 |
+ cli_hashset_destroy(&peinfo->vinfo); |
|
3194 |
+ free(section_hdr); |
|
3195 |
+ free(peinfo->section); |
|
3196 |
+ peinfo->section = NULL; |
|
3197 |
+ return -1; |
|
3198 |
+ } |
|
3199 |
+ |
|
3200 |
+ if(cli_debug_flag) { |
|
3201 |
+ char *k, *v, *s; |
|
3202 |
+ |
|
3203 |
+ /* FIXME: skip too long strings */ |
|
3204 |
+ k = cli_utf16toascii((const char*)vptr + 6, s_key_sz); |
|
3205 |
+ if(k) { |
|
3206 |
+ v = cli_utf16toascii((const char*)vptr + s_key_sz + 6, s_val_sz); |
|
3207 |
+ if(v) { |
|
3208 |
+ s = cli_str2hex((const char*)vptr + 6, s_key_sz + s_val_sz - 6); |
|
3209 |
+ if(s) { |
|
3210 |
+ cli_dbgmsg("VersionInfo (%x): '%s'='%s' - VI:%s\n", (uint32_t)(vptr - baseptr + 6), k, v, s); |
|
3211 |
+ free(s); |
|
3212 |
+ } |
|
3213 |
+ free(v); |
|
3214 |
+ } |
|
3215 |
+ free(k); |
|
3216 |
+ } |
|
3217 |
+ } |
|
3218 |
+ vptr += s_sz; |
|
3219 |
+ st_sz -= s_sz; |
|
3220 |
+ } /* enum all strings - RESUMABLE */ |
|
3221 |
+ vptr = next_vptr; |
|
3222 |
+ sfi_sz = next_sfi_sz * (sfi_sz != 0); |
|
3223 |
+ } /* enum all stringtables - RESUMABLE */ |
|
3224 |
+ break; |
|
3225 |
+ } /* look for stringfileinfo - NOT RESUMABLE */ |
|
3226 |
+ break; |
|
3227 |
+ } /* look for version_info - NOT RESUMABLE */ |
|
3228 |
+ } /* enum all version_information res - RESUMABLE */ |
|
3229 |
+ break; |
|
3226 | 3230 |
} /* while(dirs[2].Size) */ |
3227 | 3231 |
|
3228 | 3232 |
free(section_hdr); |