...
|
...
|
@@ -1,5 +1,7 @@
|
1
|
1
|
/*
|
2
|
2
|
* Copyright (C) 2007-2013 Sourcefire, Inc.
|
|
3
|
+ * Copyright (C) 2014 Cisco Systems, Inc
|
|
4
|
+ * All Rights Reserved.
|
3
|
5
|
*
|
4
|
6
|
* Authors: Tomasz Kojm
|
5
|
7
|
*
|
...
|
...
|
@@ -98,6 +100,7 @@ static inline int matcher_run(const struct cli_matcher *root,
|
98
|
98
|
struct cli_ac_result **acres,
|
99
|
99
|
fmap_t *map,
|
100
|
100
|
struct cli_bm_off *offdata,
|
|
101
|
+ struct cli_pcre_off *poffdata,
|
101
|
102
|
uint32_t *viroffset,
|
102
|
103
|
cli_ctx *ctx)
|
103
|
104
|
{
|
...
|
...
|
@@ -108,8 +111,6 @@ static inline int matcher_run(const struct cli_matcher *root,
|
108
|
108
|
const unsigned char* orig_buffer;
|
109
|
109
|
unsigned int viruses_found = 0;
|
110
|
110
|
|
111
|
|
- UNUSEDPARAM(map);
|
112
|
|
-
|
113
|
111
|
if (root->filter) {
|
114
|
112
|
if(filter_search_ext(root->filter, buffer, length, &info) == -1) {
|
115
|
113
|
/* for safety always scan last maxpatlen bytes */
|
...
|
...
|
@@ -161,6 +162,21 @@ static inline int matcher_run(const struct cli_matcher *root,
|
161
|
161
|
if (ctx && SCAN_ALL && viruses_found)
|
162
|
162
|
return CL_VIRUS;
|
163
|
163
|
|
|
164
|
+ /* due to logical triggered, pcres cannot be evaluated until after full subsig matching */
|
|
165
|
+ /* cannot save pcre execution state without possible evasion; must scan entire buffer */
|
|
166
|
+ /* however, scanning the whole buffer may require the whole buffer being loaded into memory */
|
|
167
|
+#if HAVE_PCRE
|
|
168
|
+ if (offset+length >= map->len && (buffer = fmap_need_off_once(map, 0, map->len))) {
|
|
169
|
+ cli_dbgmsg("%u+%u(%u) >= %zu: performing regex matching\n", offset, length, offset+length, map->len);
|
|
170
|
+
|
|
171
|
+ /* scan the full buffer */
|
|
172
|
+ ret = cli_pcre_scanbuf(buffer, map->len, root, mdata, acres, poffdata, ctx);
|
|
173
|
+ if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
|
|
174
|
+ return ret;
|
|
175
|
+ }
|
|
176
|
+ }
|
|
177
|
+#endif /* HAVE_PCRE */
|
|
178
|
+ /* end experimental fragment */
|
164
|
179
|
return ret;
|
165
|
180
|
}
|
166
|
181
|
|
...
|
...
|
@@ -197,7 +213,7 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset,
|
197
|
197
|
if(!acdata && (ret = cli_ac_initdata(&mdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
|
198
|
198
|
return ret;
|
199
|
199
|
|
200
|
|
- ret = matcher_run(troot, buffer, length, &virname, acdata ? (acdata[0]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, NULL, *ctx->fmap, NULL, NULL, ctx);
|
|
200
|
+ ret = matcher_run(troot, buffer, length, &virname, acdata ? (acdata[0]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, NULL, *ctx->fmap, NULL, NULL, NULL, ctx);
|
201
|
201
|
|
202
|
202
|
if(!acdata)
|
203
|
203
|
cli_ac_freedata(&mdata);
|
...
|
...
|
@@ -217,7 +233,7 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset,
|
217
|
217
|
if(!acdata && (ret = cli_ac_initdata(&mdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
|
218
|
218
|
return ret;
|
219
|
219
|
|
220
|
|
- ret = matcher_run(groot, buffer, length, &virname, acdata ? (acdata[1]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, NULL, *ctx->fmap, NULL, NULL, ctx);
|
|
220
|
+ ret = matcher_run(groot, buffer, length, &virname, acdata ? (acdata[1]): (&mdata), offset, NULL, ftype, NULL, AC_SCAN_VIR, NULL, *ctx->fmap, NULL, NULL, NULL, ctx);
|
221
|
221
|
|
222
|
222
|
if(!acdata)
|
223
|
223
|
cli_ac_freedata(&mdata);
|
...
|
...
|
@@ -725,6 +741,7 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
|
725
|
725
|
uint32_t maxpatlen, offset = 0;
|
726
|
726
|
struct cli_ac_data gdata, tdata;
|
727
|
727
|
struct cli_bm_off toff;
|
|
728
|
+ struct cli_pcre_off gpoff, tpoff;
|
728
|
729
|
unsigned char digest[CLI_HASH_AVAIL_TYPES][32];
|
729
|
730
|
struct cli_matcher *groot = NULL, *troot = NULL;
|
730
|
731
|
struct cli_target_info info;
|
...
|
...
|
@@ -791,7 +808,8 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
|
791
|
791
|
cli_targetinfo(&info, i, map);
|
792
|
792
|
|
793
|
793
|
if(!ftonly) {
|
794
|
|
- if((ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(groot, &gdata, &info))) {
|
|
794
|
+ if((ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(groot, &gdata, &info)) ||
|
|
795
|
+ (ret = cli_pcre_recaloff(groot, &gpoff, &info, ctx))) {
|
795
|
796
|
if(info.exeinfo.section)
|
796
|
797
|
free(info.exeinfo.section);
|
797
|
798
|
|
...
|
...
|
@@ -804,9 +822,12 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
|
804
|
804
|
}
|
805
|
805
|
|
806
|
806
|
if(troot) {
|
807
|
|
- if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(troot, &tdata, &info))) {
|
808
|
|
- if(!ftonly)
|
|
807
|
+ if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(troot, &tdata, &info)) ||
|
|
808
|
+ (ret = cli_pcre_recaloff(troot, &tpoff, &info, ctx))) {
|
|
809
|
+ if(!ftonly) {
|
809
|
810
|
cli_ac_freedata(&gdata);
|
|
811
|
+ cli_pcre_freeoff(&gpoff);
|
|
812
|
+ }
|
810
|
813
|
if(info.exeinfo.section)
|
811
|
814
|
free(info.exeinfo.section);
|
812
|
815
|
|
...
|
...
|
@@ -819,10 +840,13 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
|
819
|
819
|
if(troot->bm_offmode) {
|
820
|
820
|
if(map->len >= CLI_DEFAULT_BM_OFFMODE_FSIZE) {
|
821
|
821
|
if((ret = cli_bm_initoff(troot, &toff, &info))) {
|
822
|
|
- if(!ftonly)
|
|
822
|
+ if(!ftonly) {
|
823
|
823
|
cli_ac_freedata(&gdata);
|
|
824
|
+ cli_pcre_freeoff(&gpoff);
|
|
825
|
+ }
|
824
|
826
|
|
825
|
827
|
cli_ac_freedata(&tdata);
|
|
828
|
+ cli_pcre_freeoff(&tpoff);
|
826
|
829
|
if(info.exeinfo.section)
|
827
|
830
|
free(info.exeinfo.section);
|
828
|
831
|
|
...
|
...
|
@@ -878,17 +902,20 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
|
878
|
878
|
if(troot) {
|
879
|
879
|
virname = NULL;
|
880
|
880
|
viroffset = 0;
|
881
|
|
- ret = matcher_run(troot, buff, bytes, &virname, &tdata, offset, &info, ftype, ftoffset, acmode, acres, map, bm_offmode ? &toff : NULL, &viroffset, ctx);
|
|
881
|
+ ret = matcher_run(troot, buff, bytes, &virname, &tdata, offset, &info, ftype, ftoffset, acmode, acres, map, bm_offmode ? &toff : NULL, &tpoff, &viroffset, ctx);
|
882
|
882
|
|
883
|
883
|
if (virname) {
|
884
|
884
|
/* virname already appended by matcher_run */
|
885
|
885
|
viruses_found = 1;
|
886
|
886
|
}
|
887
|
887
|
if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
|
888
|
|
- if(!ftonly)
|
|
888
|
+ if(!ftonly) {
|
889
|
889
|
cli_ac_freedata(&gdata);
|
|
890
|
+ cli_pcre_freeoff(&gpoff);
|
|
891
|
+ }
|
890
|
892
|
|
891
|
893
|
cli_ac_freedata(&tdata);
|
|
894
|
+ cli_pcre_freeoff(&tpoff);
|
892
|
895
|
if(bm_offmode)
|
893
|
896
|
cli_bm_freeoff(&toff);
|
894
|
897
|
|
...
|
...
|
@@ -906,7 +933,7 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
|
906
|
906
|
if(!ftonly) {
|
907
|
907
|
virname = NULL;
|
908
|
908
|
viroffset = 0;
|
909
|
|
- ret = matcher_run(groot, buff, bytes, &virname, &gdata, offset, &info, ftype, ftoffset, acmode, acres, map, NULL, &viroffset, ctx);
|
|
909
|
+ ret = matcher_run(groot, buff, bytes, &virname, &gdata, offset, &info, ftype, ftoffset, acmode, acres, map, NULL, &gpoff, &viroffset, ctx);
|
910
|
910
|
|
911
|
911
|
if (virname) {
|
912
|
912
|
/* virname already appended by matcher_run */
|
...
|
...
|
@@ -914,8 +941,10 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
|
914
|
914
|
}
|
915
|
915
|
if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
|
916
|
916
|
cli_ac_freedata(&gdata);
|
|
917
|
+ cli_pcre_freeoff(&gpoff);
|
917
|
918
|
if(troot) {
|
918
|
919
|
cli_ac_freedata(&tdata);
|
|
920
|
+ cli_pcre_freeoff(&tpoff);
|
919
|
921
|
if(bm_offmode)
|
920
|
922
|
cli_bm_freeoff(&toff);
|
921
|
923
|
}
|
...
|
...
|
@@ -957,102 +986,6 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
|
957
|
957
|
offset += bytes - maxpatlen;
|
958
|
958
|
}
|
959
|
959
|
|
960
|
|
- /* lsig '=' op does not work if pcre match occurs after AC matching */
|
961
|
|
- /* cannot save pcre execution state without possible evasion; must scan entire buffer */
|
962
|
|
- /* however, scanning the whole buffer may require the whole buffer being loaded into memory */
|
963
|
|
- /* this should also be part of matcher_run but it cannot as matcher_run is done on partial buffers */
|
964
|
|
-#if HAVE_PCRE
|
965
|
|
- if((buff = fmap_need_off_once(map, 0, map->len))) {
|
966
|
|
- if (!ftonly) {
|
967
|
|
- struct cli_pcre_off poff;
|
968
|
|
-
|
969
|
|
- /* calculate the relative offsets */
|
970
|
|
- ret = cli_pcre_recaloff(groot, &poff, &info, ctx);
|
971
|
|
- if (ret != CL_SUCCESS) {
|
972
|
|
- cli_ac_freedata(&gdata);
|
973
|
|
- cli_ac_freedata(&tdata);
|
974
|
|
- if(bm_offmode)
|
975
|
|
- cli_bm_freeoff(&toff);
|
976
|
|
-
|
977
|
|
- if(info.exeinfo.section)
|
978
|
|
- free(info.exeinfo.section);
|
979
|
|
-
|
980
|
|
- cli_hashset_destroy(&info.exeinfo.vinfo);
|
981
|
|
- cl_hash_destroy(md5ctx);
|
982
|
|
- cl_hash_destroy(sha1ctx);
|
983
|
|
- cl_hash_destroy(sha256ctx);
|
984
|
|
- return ret;
|
985
|
|
- }
|
986
|
|
-
|
987
|
|
- /* scan the full buffer */
|
988
|
|
- ret = cli_pcre_scanbuf(buff, map->len, groot, &gdata, acres, &poff, ctx);
|
989
|
|
- if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
|
990
|
|
- cli_ac_freedata(&gdata);
|
991
|
|
- cli_ac_freedata(&tdata);
|
992
|
|
- if(bm_offmode)
|
993
|
|
- cli_bm_freeoff(&toff);
|
994
|
|
-
|
995
|
|
- if(info.exeinfo.section)
|
996
|
|
- free(info.exeinfo.section);
|
997
|
|
-
|
998
|
|
- cli_pcre_freeoff(&poff);
|
999
|
|
-
|
1000
|
|
- cli_hashset_destroy(&info.exeinfo.vinfo);
|
1001
|
|
- cl_hash_destroy(md5ctx);
|
1002
|
|
- cl_hash_destroy(sha1ctx);
|
1003
|
|
- cl_hash_destroy(sha256ctx);
|
1004
|
|
- return ret;
|
1005
|
|
- }
|
1006
|
|
- cli_pcre_freeoff(&poff);
|
1007
|
|
- }
|
1008
|
|
- if (troot) {
|
1009
|
|
- struct cli_pcre_off poff;
|
1010
|
|
-
|
1011
|
|
- /* calculate the relative offsets */
|
1012
|
|
- ret = cli_pcre_recaloff(troot, &poff, &info, ctx);
|
1013
|
|
- if (ret != CL_SUCCESS) {
|
1014
|
|
- cli_ac_freedata(&gdata);
|
1015
|
|
- cli_ac_freedata(&tdata);
|
1016
|
|
- if(bm_offmode)
|
1017
|
|
- cli_bm_freeoff(&toff);
|
1018
|
|
-
|
1019
|
|
- if(info.exeinfo.section)
|
1020
|
|
- free(info.exeinfo.section);
|
1021
|
|
-
|
1022
|
|
- cli_hashset_destroy(&info.exeinfo.vinfo);
|
1023
|
|
- cl_hash_destroy(md5ctx);
|
1024
|
|
- cl_hash_destroy(sha1ctx);
|
1025
|
|
- cl_hash_destroy(sha256ctx);
|
1026
|
|
- return ret;
|
1027
|
|
- }
|
1028
|
|
-
|
1029
|
|
- /* scan the full buffer */
|
1030
|
|
- ret = cli_pcre_scanbuf(buff, map->len, troot, &tdata, acres, &poff, ctx);
|
1031
|
|
- if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
|
1032
|
|
- if(!ftonly)
|
1033
|
|
- cli_ac_freedata(&gdata);
|
1034
|
|
-
|
1035
|
|
- cli_ac_freedata(&tdata);
|
1036
|
|
- if(bm_offmode)
|
1037
|
|
- cli_bm_freeoff(&toff);
|
1038
|
|
-
|
1039
|
|
- if(info.exeinfo.section)
|
1040
|
|
- free(info.exeinfo.section);
|
1041
|
|
-
|
1042
|
|
- cli_pcre_freeoff(&poff);
|
1043
|
|
-
|
1044
|
|
- cli_hashset_destroy(&info.exeinfo.vinfo);
|
1045
|
|
- cl_hash_destroy(md5ctx);
|
1046
|
|
- cl_hash_destroy(sha1ctx);
|
1047
|
|
- cl_hash_destroy(sha256ctx);
|
1048
|
|
- return ret;
|
1049
|
|
- }
|
1050
|
|
- cli_pcre_freeoff(&poff);
|
1051
|
|
- }
|
1052
|
|
- }
|
1053
|
|
-#endif /* HAVE_PCRE */
|
1054
|
|
- /* end experimental fragment */
|
1055
|
|
-
|
1056
|
960
|
if(!ftonly && hdb) {
|
1057
|
961
|
enum CLI_HASH_TYPE hashtype, hashtype2;
|
1058
|
962
|
|
...
|
...
|
@@ -1137,6 +1070,7 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
|
1137
|
1137
|
viruses_found++;
|
1138
|
1138
|
|
1139
|
1139
|
cli_ac_freedata(&tdata);
|
|
1140
|
+ cli_pcre_freeoff(&tpoff);
|
1140
|
1141
|
if(bm_offmode)
|
1141
|
1142
|
cli_bm_freeoff(&toff);
|
1142
|
1143
|
}
|
...
|
...
|
@@ -1145,6 +1079,7 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
|
1145
|
1145
|
if(ret != CL_VIRUS || SCAN_ALL)
|
1146
|
1146
|
ret = cli_lsig_eval(ctx, groot, &gdata, &info, (const char *)refhash);
|
1147
|
1147
|
cli_ac_freedata(&gdata);
|
|
1148
|
+ cli_pcre_freeoff(&gpoff);
|
1148
|
1149
|
}
|
1149
|
1150
|
|
1150
|
1151
|
if(info.exeinfo.section)
|