...
|
...
|
@@ -2802,8 +2802,8 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1) {
|
2802
|
2802
|
uint32_t e_lfanew; /* address of new exe header */
|
2803
|
2803
|
struct pe_image_file_hdr file_hdr;
|
2804
|
2804
|
union {
|
2805
|
|
- struct pe_image_optional_hdr64 opt64;
|
2806
|
|
- struct pe_image_optional_hdr32 opt32;
|
|
2805
|
+ struct pe_image_optional_hdr64 opt64;
|
|
2806
|
+ struct pe_image_optional_hdr32 opt32;
|
2807
|
2807
|
} pe_opt;
|
2808
|
2808
|
const struct pe_image_section_hdr *section_hdr;
|
2809
|
2809
|
ssize_t at;
|
...
|
...
|
@@ -2816,65 +2816,69 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1) {
|
2816
|
2816
|
SHA1Context sha1;
|
2817
|
2817
|
|
2818
|
2818
|
if(!(DCONF & PE_CONF_CATALOG))
|
2819
|
|
- return CL_EFORMAT;
|
|
2819
|
+ return CL_EFORMAT;
|
2820
|
2820
|
|
2821
|
2821
|
if(fmap_readn(map, &e_magic, 0, sizeof(e_magic)) != sizeof(e_magic))
|
2822
|
|
- return CL_EFORMAT;
|
|
2822
|
+ return CL_EFORMAT;
|
2823
|
2823
|
|
2824
|
2824
|
if(EC16(e_magic) != PE_IMAGE_DOS_SIGNATURE && EC16(e_magic) != PE_IMAGE_DOS_SIGNATURE_OLD)
|
2825
|
|
- return CL_EFORMAT;
|
|
2825
|
+ return CL_EFORMAT;
|
2826
|
2826
|
|
2827
|
2827
|
if(fmap_readn(map, &e_lfanew, 58 + sizeof(e_magic), sizeof(e_lfanew)) != sizeof(e_lfanew))
|
2828
|
|
- return CL_EFORMAT;
|
|
2828
|
+ return CL_EFORMAT;
|
2829
|
2829
|
|
2830
|
2830
|
e_lfanew = EC32(e_lfanew);
|
2831
|
2831
|
if(!e_lfanew)
|
2832
|
|
- return CL_EFORMAT;
|
|
2832
|
+ return CL_EFORMAT;
|
2833
|
2833
|
|
2834
|
2834
|
if(fmap_readn(map, &file_hdr, e_lfanew, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr))
|
2835
|
|
- return CL_EFORMAT;
|
|
2835
|
+ return CL_EFORMAT;
|
2836
|
2836
|
|
2837
|
2837
|
if(EC32(file_hdr.Magic) != PE_IMAGE_NT_SIGNATURE)
|
2838
|
|
- return CL_EFORMAT;
|
|
2838
|
+ return CL_EFORMAT;
|
2839
|
2839
|
|
2840
|
2840
|
nsections = EC16(file_hdr.NumberOfSections);
|
2841
|
2841
|
if(nsections < 1 || nsections > 96)
|
2842
|
|
- return CL_EFORMAT;
|
|
2842
|
+ return CL_EFORMAT;
|
2843
|
2843
|
|
2844
|
2844
|
if(EC16(file_hdr.SizeOfOptionalHeader) < sizeof(struct pe_image_optional_hdr32))
|
2845
|
|
- return CL_EFORMAT;
|
|
2845
|
+ return CL_EFORMAT;
|
2846
|
2846
|
|
2847
|
2847
|
at = e_lfanew + sizeof(struct pe_image_file_hdr);
|
2848
|
2848
|
if(fmap_readn(map, &optional_hdr32, at, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32))
|
2849
|
|
- return CL_EFORMAT;
|
|
2849
|
+ return CL_EFORMAT;
|
|
2850
|
+
|
2850
|
2851
|
at += sizeof(struct pe_image_optional_hdr32);
|
2851
|
2852
|
|
2852
|
2853
|
/* This will be a chicken and egg problem until we drop 9x */
|
2853
|
2854
|
if(EC16(optional_hdr64.Magic)==PE32P_SIGNATURE) {
|
2854
|
2855
|
if(EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr64))
|
2855
|
|
- return CL_EFORMAT;
|
2856
|
|
- pe_plus = 1;
|
|
2856
|
+ return CL_EFORMAT;
|
|
2857
|
+
|
|
2858
|
+ pe_plus = 1;
|
2857
|
2859
|
}
|
2858
|
2860
|
|
2859
|
2861
|
if(!pe_plus) { /* PE */
|
2860
|
|
- if (EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr32)) {
|
2861
|
|
- /* Seek to the end of the long header */
|
2862
|
|
- at += EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32);
|
2863
|
|
- }
|
|
2862
|
+ if (EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr32)) {
|
|
2863
|
+ /* Seek to the end of the long header */
|
|
2864
|
+ at += EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32);
|
|
2865
|
+ }
|
2864
|
2866
|
|
2865
|
|
- hdr_size = EC32(optional_hdr32.SizeOfHeaders);
|
2866
|
|
- dirs = optional_hdr32.DataDirectory;
|
|
2867
|
+ hdr_size = EC32(optional_hdr32.SizeOfHeaders);
|
|
2868
|
+ dirs = optional_hdr32.DataDirectory;
|
2867
|
2869
|
} else { /* PE+ */
|
|
2870
|
+ size_t readlen = sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32);
|
2868
|
2871
|
/* read the remaining part of the header */
|
2869
|
|
- 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))
|
2870
|
|
- return CL_EFORMAT;
|
2871
|
|
- at += sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32);
|
2872
|
|
- hdr_size = EC32(optional_hdr64.SizeOfHeaders);
|
2873
|
|
- dirs = optional_hdr64.DataDirectory;
|
|
2872
|
+ if(fmap_readn(map, &optional_hdr32 + 1, at, readlen) != readlen)
|
|
2873
|
+ return CL_EFORMAT;
|
|
2874
|
+
|
|
2875
|
+ at += sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32);
|
|
2876
|
+ hdr_size = EC32(optional_hdr64.SizeOfHeaders);
|
|
2877
|
+ dirs = optional_hdr64.DataDirectory;
|
2874
|
2878
|
}
|
2875
|
2879
|
|
2876
|
2880
|
if(!cli_hm_have_size(ctx->engine->hm_fp, CLI_HASH_SHA1, 2) && dirs[4].Size < 8)
|
2877
|
|
- return CL_BREAK;
|
|
2881
|
+ return CL_BREAK;
|
2878
|
2882
|
|
2879
|
2883
|
fsize = map->len;
|
2880
|
2884
|
|
...
|
...
|
@@ -2883,57 +2887,58 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1) {
|
2883
|
2883
|
|
2884
|
2884
|
section_hdr = fmap_need_off_once(map, at, sizeof(*section_hdr) * nsections);
|
2885
|
2885
|
if(!section_hdr)
|
2886
|
|
- return CL_EFORMAT;
|
|
2886
|
+ return CL_EFORMAT;
|
|
2887
|
+
|
2887
|
2888
|
at += sizeof(*section_hdr) * nsections;
|
2888
|
2889
|
|
2889
|
2890
|
exe_sections = (struct cli_exe_section *) cli_calloc(nsections, sizeof(struct cli_exe_section));
|
2890
|
2891
|
if(!exe_sections)
|
2891
|
|
- return CL_EMEM;
|
|
2892
|
+ return CL_EMEM;
|
2892
|
2893
|
|
2893
|
2894
|
for(i = 0; falign!=0x200 && i<nsections; i++) {
|
2894
|
|
- /* file alignment fallback mode - blah */
|
2895
|
|
- if (falign && section_hdr[i].SizeOfRawData && EC32(section_hdr[i].PointerToRawData)%falign && !(EC32(section_hdr[i].PointerToRawData)%0x200))
|
2896
|
|
- falign = 0x200;
|
|
2895
|
+ /* file alignment fallback mode - blah */
|
|
2896
|
+ if (falign && section_hdr[i].SizeOfRawData && EC32(section_hdr[i].PointerToRawData)%falign && !(EC32(section_hdr[i].PointerToRawData)%0x200))
|
|
2897
|
+ falign = 0x200;
|
2897
|
2898
|
}
|
2898
|
2899
|
|
2899
|
2900
|
hdr_size = PESALIGN(hdr_size, falign); /* Aligned headers virtual size */
|
2900
|
2901
|
|
2901
|
2902
|
for(i = 0; i < nsections; i++) {
|
2902
|
|
- exe_sections[i].rva = PEALIGN(EC32(section_hdr[i].VirtualAddress), valign);
|
2903
|
|
- exe_sections[i].vsz = PESALIGN(EC32(section_hdr[i].VirtualSize), valign);
|
2904
|
|
- exe_sections[i].raw = PEALIGN(EC32(section_hdr[i].PointerToRawData), falign);
|
2905
|
|
- exe_sections[i].rsz = PESALIGN(EC32(section_hdr[i].SizeOfRawData), falign);
|
|
2903
|
+ exe_sections[i].rva = PEALIGN(EC32(section_hdr[i].VirtualAddress), valign);
|
|
2904
|
+ exe_sections[i].vsz = PESALIGN(EC32(section_hdr[i].VirtualSize), valign);
|
|
2905
|
+ exe_sections[i].raw = PEALIGN(EC32(section_hdr[i].PointerToRawData), falign);
|
|
2906
|
+ exe_sections[i].rsz = PESALIGN(EC32(section_hdr[i].SizeOfRawData), falign);
|
2906
|
2907
|
|
2907
|
|
- if (!exe_sections[i].vsz && exe_sections[i].rsz)
|
2908
|
|
- exe_sections[i].vsz=PESALIGN(exe_sections[i].ursz, valign);
|
|
2908
|
+ if (!exe_sections[i].vsz && exe_sections[i].rsz)
|
|
2909
|
+ exe_sections[i].vsz=PESALIGN(exe_sections[i].ursz, valign);
|
2909
|
2910
|
|
2910
|
|
- if (exe_sections[i].rsz && fsize>exe_sections[i].raw && !CLI_ISCONTAINED(0, (uint32_t) fsize, exe_sections[i].raw, exe_sections[i].rsz))
|
2911
|
|
- exe_sections[i].rsz = fsize - exe_sections[i].raw;
|
|
2911
|
+ if (exe_sections[i].rsz && fsize>exe_sections[i].raw && !CLI_ISCONTAINED(0, (uint32_t) fsize, exe_sections[i].raw, exe_sections[i].rsz))
|
|
2912
|
+ exe_sections[i].rsz = fsize - exe_sections[i].raw;
|
2912
|
2913
|
|
2913
|
|
- if (exe_sections[i].rsz && exe_sections[i].raw >= fsize) {
|
2914
|
|
- free(exe_sections);
|
2915
|
|
- return CL_EFORMAT;
|
2916
|
|
- }
|
|
2914
|
+ if (exe_sections[i].rsz && exe_sections[i].raw >= fsize) {
|
|
2915
|
+ free(exe_sections);
|
|
2916
|
+ return CL_EFORMAT;
|
|
2917
|
+ }
|
2917
|
2918
|
|
2918
|
|
- if (exe_sections[i].urva>>31 || exe_sections[i].uvsz>>31 || (exe_sections[i].rsz && exe_sections[i].uraw>>31) || exe_sections[i].ursz>>31) {
|
2919
|
|
- free(exe_sections);
|
2920
|
|
- return CL_EFORMAT;
|
2921
|
|
- }
|
|
2919
|
+ if (exe_sections[i].urva>>31 || exe_sections[i].uvsz>>31 || (exe_sections[i].rsz && exe_sections[i].uraw>>31) || exe_sections[i].ursz>>31) {
|
|
2920
|
+ free(exe_sections);
|
|
2921
|
+ return CL_EFORMAT;
|
|
2922
|
+ }
|
2922
|
2923
|
}
|
2923
|
2924
|
|
2924
|
2925
|
cli_qsort(exe_sections, nsections, sizeof(*exe_sections), sort_sects);
|
2925
|
2926
|
|
2926
|
2927
|
SHA1Init(&sha1);
|
2927
|
2928
|
|
2928
|
|
-#define hash_chunk(where, size) \
|
2929
|
|
- do { \
|
2930
|
|
- const uint8_t *hptr; \
|
2931
|
|
- if(!(size)) break; \
|
2932
|
|
- if(!(hptr = fmap_need_off_once(map, where, size))){ \
|
2933
|
|
- free(exe_sections); \
|
2934
|
|
- return CL_EFORMAT; \
|
2935
|
|
- } \
|
2936
|
|
- SHA1Update(&sha1, hptr, size); \
|
|
2929
|
+#define hash_chunk(where, size) \
|
|
2930
|
+ do { \
|
|
2931
|
+ const uint8_t *hptr; \
|
|
2932
|
+ if(!(size)) break; \
|
|
2933
|
+ if(!(hptr = fmap_need_off_once(map, where, size))){ \
|
|
2934
|
+ free(exe_sections); \
|
|
2935
|
+ return CL_EFORMAT; \
|
|
2936
|
+ } \
|
|
2937
|
+ SHA1Update(&sha1, hptr, size); \
|
2937
|
2938
|
} while(0)
|
2938
|
2939
|
|
2939
|
2940
|
/* MZ to checksum */
|
...
|
...
|
@@ -2944,15 +2949,15 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1) {
|
2944
|
2944
|
|
2945
|
2945
|
/* Checksum to security */
|
2946
|
2946
|
if(pe_plus)
|
2947
|
|
- hlen = offsetof(struct pe_image_optional_hdr64, DataDirectory[4]) - offsetof(struct pe_image_optional_hdr64, CheckSum) - 4;
|
|
2947
|
+ hlen = offsetof(struct pe_image_optional_hdr64, DataDirectory[4]) - offsetof(struct pe_image_optional_hdr64, CheckSum) - 4;
|
2948
|
2948
|
else
|
2949
|
|
- hlen = offsetof(struct pe_image_optional_hdr32, DataDirectory[4]) - offsetof(struct pe_image_optional_hdr32, CheckSum) - 4;
|
|
2949
|
+ hlen = offsetof(struct pe_image_optional_hdr32, DataDirectory[4]) - offsetof(struct pe_image_optional_hdr32, CheckSum) - 4;
|
2950
|
2950
|
hash_chunk(at, hlen);
|
2951
|
2951
|
at += hlen + 8;
|
2952
|
2952
|
|
2953
|
2953
|
if(at > hdr_size) {
|
2954
|
|
- free(exe_sections);
|
2955
|
|
- return CL_EFORMAT;
|
|
2954
|
+ free(exe_sections);
|
|
2955
|
+ return CL_EFORMAT;
|
2956
|
2956
|
}
|
2957
|
2957
|
|
2958
|
2958
|
/* Security to End of header */
|
...
|
...
|
@@ -2962,36 +2967,40 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1) {
|
2962
|
2962
|
/* Sections */
|
2963
|
2963
|
at = hdr_size;
|
2964
|
2964
|
for(i = 0; i < nsections; i++) {
|
2965
|
|
- if(!exe_sections[i].rsz)
|
2966
|
|
- continue;
|
2967
|
|
- hash_chunk(exe_sections[i].raw, exe_sections[i].rsz);
|
2968
|
|
- at += exe_sections[i].rsz;
|
|
2965
|
+ if(!exe_sections[i].rsz)
|
|
2966
|
+ continue;
|
|
2967
|
+
|
|
2968
|
+ hash_chunk(exe_sections[i].raw, exe_sections[i].rsz);
|
|
2969
|
+ at += exe_sections[i].rsz;
|
2969
|
2970
|
}
|
2970
|
2971
|
|
2971
|
2972
|
if(at < fsize) {
|
2972
|
|
- hlen = fsize - at;
|
2973
|
|
- if(dirs[4].Size > hlen) {
|
2974
|
|
- free(exe_sections);
|
2975
|
|
- return CL_EFORMAT;
|
2976
|
|
- }
|
2977
|
|
- hlen -= dirs[4].Size;
|
2978
|
|
- hash_chunk(at, hlen);
|
2979
|
|
- at += hlen;
|
|
2973
|
+ hlen = fsize - at;
|
|
2974
|
+ if(dirs[4].Size > hlen) {
|
|
2975
|
+ free(exe_sections);
|
|
2976
|
+ return CL_EFORMAT;
|
|
2977
|
+ }
|
|
2978
|
+
|
|
2979
|
+ hlen -= dirs[4].Size;
|
|
2980
|
+ hash_chunk(at, hlen);
|
|
2981
|
+ at += hlen;
|
2980
|
2982
|
}
|
2981
|
2983
|
free(exe_sections);
|
2982
|
2984
|
|
2983
|
2985
|
SHA1Final(&sha1, authsha1);
|
2984
|
2986
|
|
2985
|
2987
|
if(cli_debug_flag) {
|
2986
|
|
- char shatxt[SHA1_HASH_SIZE*2+1];
|
2987
|
|
- for(i=0; i<SHA1_HASH_SIZE; i++)
|
2988
|
|
- sprintf(&shatxt[i*2], "%02x", authsha1[i]);
|
2989
|
|
- cli_dbgmsg("Authenticode: %s\n", shatxt);
|
|
2988
|
+ char shatxt[SHA1_HASH_SIZE*2+1];
|
|
2989
|
+ for(i=0; i<SHA1_HASH_SIZE; i++)
|
|
2990
|
+ sprintf(&shatxt[i*2], "%02x", authsha1[i]);
|
|
2991
|
+ cli_dbgmsg("Authenticode: %s\n", shatxt);
|
2990
|
2992
|
}
|
2991
|
2993
|
|
2992
|
2994
|
hlen = dirs[4].Size;
|
2993
|
2995
|
if(hlen < 8)
|
2994
|
|
- return CL_VIRUS;
|
|
2996
|
+ return CL_VIRUS;
|
|
2997
|
+
|
2995
|
2998
|
hlen -= 8;
|
|
2999
|
+
|
2996
|
3000
|
return asn1_check_mscat((struct cl_engine *)(ctx->engine), map, at + 8, hlen, authsha1);
|
2997
|
3001
|
}
|