git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@1155 77e5149b-7576-45b1-b177-96237e5ba77b
Tomasz Kojm authored on 2004/12/03 09:28:16... | ... |
@@ -1,3 +1,8 @@ |
1 |
+Fri Dec 3 03:32:17 CET 2004 (tk) |
|
2 |
+--------------------------------- |
|
3 |
+ * libclamav: attempt to rebuild PE structure from UPX compressed files |
|
4 |
+ (code from aCaB) |
|
5 |
+ |
|
1 | 6 |
Thu Dec 2 11:10:31 GMT 2004 (njh) |
2 | 7 |
---------------------------------- |
3 | 8 |
* clamav-milter: --internal now notices when the database has been |
... | ... |
@@ -154,7 +154,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c |
154 | 154 |
struct stat sb; |
155 | 155 |
char sname[9], buff[256], *tempfile; |
156 | 156 |
int i, found, upx_success = 0, min = 0, max = 0, ret; |
157 |
- int (*upxfn)(char *, int , char *, int) = NULL; |
|
157 |
+ int (*upxfn)(char *, int , char *, int *, uint32_t, uint32_t, uint32_t) = NULL; |
|
158 | 158 |
char *src = NULL, *dest = NULL; |
159 | 159 |
int ssize = -1, dsize = -1, ndesc; |
160 | 160 |
|
... | ... |
@@ -717,6 +717,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c |
717 | 717 |
fsync(ndesc); |
718 | 718 |
lseek(ndesc, 0, SEEK_SET); |
719 | 719 |
|
720 |
+ cli_dbgmsg("***** Scanning rebuilt PE file *****\n"); |
|
720 | 721 |
if(cli_magic_scandesc(ndesc, virname, scanned, root, limits, options, arec, mrec) == CL_VIRUS) { |
721 | 722 |
free(section_hdr); |
722 | 723 |
close(ndesc); |
... | ... |
@@ -909,6 +910,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c |
909 | 909 |
fsync(ndesc); |
910 | 910 |
lseek(ndesc, 0, SEEK_SET); |
911 | 911 |
|
912 |
+ cli_dbgmsg("***** Scanning rebuilt PE file *****\n"); |
|
912 | 913 |
if(cli_magic_scandesc(ndesc, virname, scanned, root, limits, options, arec, mrec) == CL_VIRUS) { |
913 | 914 |
free(section_hdr); |
914 | 915 |
close(ndesc); |
... | ... |
@@ -987,7 +989,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c |
987 | 987 |
return CL_EMEM; |
988 | 988 |
} |
989 | 989 |
|
990 |
- if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) { |
|
990 |
+ if((dest = (char *) cli_calloc(dsize + 1024 + nsections * 40, sizeof(char))) == NULL) { |
|
991 | 991 |
free(section_hdr); |
992 | 992 |
free(src); |
993 | 993 |
return CL_EMEM; |
... | ... |
@@ -1037,12 +1039,12 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c |
1037 | 1037 |
|
1038 | 1038 |
if(buff[1] != '\xbe' || skew <= 0 || skew > 0xfff ) { /* FIXME: legit skews?? */ |
1039 | 1039 |
skew = 0; |
1040 |
- if(!upxfn(src, ssize, dest, dsize)) |
|
1040 |
+ if(upxfn(src, ssize, dest, &dsize, EC32(section_hdr[i].VirtualAddress), EC32(section_hdr[i + 1].VirtualAddress), EC32(optional_hdr.AddressOfEntryPoint)) >= 0) |
|
1041 | 1041 |
upx_success = 1; |
1042 | 1042 |
|
1043 | 1043 |
} else { |
1044 | 1044 |
cli_dbgmsg("UPX: UPX1 seems skewed by %d bytes\n", skew); |
1045 |
- if(!upxfn(src + skew, ssize - skew, dest, dsize) || !upxfn(src, ssize, dest, dsize)) |
|
1045 |
+ if(upxfn(src + skew, ssize - skew, dest, &dsize, EC32(section_hdr[i].VirtualAddress), EC32(section_hdr[i + 1].VirtualAddress), EC32(optional_hdr.AddressOfEntryPoint)-skew) >= 0 || upxfn(src, ssize, dest, &dsize, EC32(section_hdr[i].VirtualAddress), EC32(section_hdr[i + 1].VirtualAddress), EC32(optional_hdr.AddressOfEntryPoint)) >= 0) |
|
1046 | 1046 |
upx_success = 1; |
1047 | 1047 |
} |
1048 | 1048 |
|
... | ... |
@@ -1053,7 +1055,8 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c |
1053 | 1053 |
} |
1054 | 1054 |
|
1055 | 1055 |
if(!upx_success && upxfn != upx_inflate2b) { |
1056 |
- if(upx_inflate2b(src, ssize, dest, dsize) && upx_inflate2b(src + 0x15, ssize - 0x15, dest, dsize) ) { |
|
1056 |
+ if(upx_inflate2b(src, ssize, dest, &dsize, EC32(section_hdr[i].VirtualAddress), EC32(section_hdr[i + 1].VirtualAddress), EC32(optional_hdr.AddressOfEntryPoint)) == -1 && upx_inflate2b(src + 0x15, ssize - 0x15, dest, &dsize, EC32(section_hdr[i].VirtualAddress), EC32(section_hdr[i + 1].VirtualAddress), EC32(optional_hdr.AddressOfEntryPoint) - 0x15) == -1) { |
|
1057 |
+ |
|
1057 | 1058 |
cli_dbgmsg("UPX: NRV2B decompressor failed\n"); |
1058 | 1059 |
} else { |
1059 | 1060 |
upx_success = 1; |
... | ... |
@@ -1062,7 +1065,8 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c |
1062 | 1062 |
} |
1063 | 1063 |
|
1064 | 1064 |
if(!upx_success && upxfn != upx_inflate2d) { |
1065 |
- if(upx_inflate2d(src, ssize, dest, dsize) && upx_inflate2d(src + 0x15, ssize - 0x15, dest, dsize) ) { |
|
1065 |
+ if(upx_inflate2d(src, ssize, dest, &dsize, EC32(section_hdr[i].VirtualAddress), EC32(section_hdr[i + 1].VirtualAddress), EC32(optional_hdr.AddressOfEntryPoint)) == -1 && upx_inflate2d(src + 0x15, ssize - 0x15, dest, &dsize, EC32(section_hdr[i].VirtualAddress), EC32(section_hdr[i + 1].VirtualAddress), EC32(optional_hdr.AddressOfEntryPoint) - 0x15) == -1) { |
|
1066 |
+ |
|
1066 | 1067 |
cli_dbgmsg("UPX: NRV2D decompressor failed\n"); |
1067 | 1068 |
} else { |
1068 | 1069 |
upx_success = 1; |
... | ... |
@@ -1071,7 +1075,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c |
1071 | 1071 |
} |
1072 | 1072 |
|
1073 | 1073 |
if(!upx_success && upxfn != upx_inflate2e) { |
1074 |
- if(upx_inflate2e(src, ssize, dest, dsize) && upx_inflate2e(src + 0x15, ssize - 0x15, dest, dsize) ) { |
|
1074 |
+ if(upx_inflate2e(src, ssize, dest, &dsize, EC32(section_hdr[i].VirtualAddress), EC32(section_hdr[i + 1].VirtualAddress), EC32(optional_hdr.AddressOfEntryPoint)) == -1 && upx_inflate2e(src + 0x15, ssize - 0x15, dest, &dsize, EC32(section_hdr[i].VirtualAddress), EC32(section_hdr[i + 1].VirtualAddress), EC32(optional_hdr.AddressOfEntryPoint) - 0x15) == -1) { |
|
1075 | 1075 |
cli_dbgmsg("UPX: NRV2E decompressor failed\n"); |
1076 | 1076 |
} else { |
1077 | 1077 |
upx_success = 1; |
... | ... |
@@ -1087,40 +1091,45 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c |
1087 | 1087 |
} |
1088 | 1088 |
|
1089 | 1089 |
if(upx_success) { |
1090 |
- int ndesc; |
|
1091 |
- |
|
1092 |
- if(cli_leavetemps_flag) { |
|
1093 |
- tempfile = cli_gentemp(NULL); |
|
1094 |
- if((ndesc = open(tempfile, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU)) < 0) { |
|
1095 |
- cli_dbgmsg("UPX/FSG: Can't create file %s\n", tempfile); |
|
1096 |
- free(tempfile); |
|
1097 |
- free(section_hdr); |
|
1098 |
- free(src); |
|
1099 |
- free(dest); |
|
1100 |
- return CL_EIO; |
|
1101 |
- } |
|
1090 |
+ free(src); |
|
1091 |
+ free(section_hdr); |
|
1102 | 1092 |
|
1103 |
- if(write(ndesc, dest, dsize) != dsize) { |
|
1104 |
- cli_dbgmsg("UPX/FSG: Can't write %d bytes\n", dsize); |
|
1105 |
- free(tempfile); |
|
1106 |
- free(section_hdr); |
|
1107 |
- free(src); |
|
1108 |
- free(dest); |
|
1109 |
- return CL_EIO; |
|
1110 |
- } |
|
1093 |
+ tempfile = cli_gentemp(NULL); |
|
1094 |
+ if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) < 0) { |
|
1095 |
+ cli_dbgmsg("UPX/FSG: Can't create file %s\n", tempfile); |
|
1096 |
+ free(tempfile); |
|
1097 |
+ free(dest); |
|
1098 |
+ return CL_EIO; |
|
1099 |
+ } |
|
1111 | 1100 |
|
1101 |
+ if(write(ndesc, dest, dsize) != dsize) { |
|
1102 |
+ cli_dbgmsg("UPX/FSG: Can't write %d bytes\n", dsize); |
|
1103 |
+ free(tempfile); |
|
1104 |
+ free(dest); |
|
1112 | 1105 |
close(ndesc); |
1106 |
+ return CL_EIO; |
|
1107 |
+ } |
|
1108 |
+ |
|
1109 |
+ free(dest); |
|
1110 |
+ fsync(ndesc); |
|
1111 |
+ lseek(ndesc, 0, SEEK_SET); |
|
1112 |
+ |
|
1113 |
+ if(cli_leavetemps_flag) |
|
1113 | 1114 |
cli_dbgmsg("UPX/FSG: Decompressed data saved in %s\n", tempfile); |
1115 |
+ |
|
1116 |
+ cli_dbgmsg("***** Scanning rebuilt PE file *****\n"); |
|
1117 |
+ if((ret = cli_magic_scandesc(ndesc, virname, scanned, root, limits, options, arec, mrec)) == CL_VIRUS) { |
|
1118 |
+ close(ndesc); |
|
1119 |
+ if(!cli_leavetemps_flag) |
|
1120 |
+ unlink(tempfile); |
|
1114 | 1121 |
free(tempfile); |
1122 |
+ return CL_VIRUS; |
|
1115 | 1123 |
} |
1116 | 1124 |
|
1117 |
- if(scanned) |
|
1118 |
- *scanned += dsize / CL_COUNT_PRECISION; |
|
1119 |
- |
|
1120 |
- ret = cl_scanbuff(dest, dsize, virname, root); |
|
1121 |
- free(section_hdr); |
|
1122 |
- free(src); |
|
1123 |
- free(dest); |
|
1125 |
+ close(ndesc); |
|
1126 |
+ if(!cli_leavetemps_flag) |
|
1127 |
+ unlink(tempfile); |
|
1128 |
+ free(tempfile); |
|
1124 | 1129 |
return ret; |
1125 | 1130 |
} |
1126 | 1131 |
} |
... | ... |
@@ -1192,6 +1201,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c |
1192 | 1192 |
EC32(optional_hdr.DataDirectory[2].Size))) { |
1193 | 1193 |
case 1: |
1194 | 1194 |
cli_dbgmsg("Petite: Unpacked and rebuilt executable saved in %s\n", tempfile); |
1195 |
+ cli_dbgmsg("***** Scanning rebuilt PE file *****\n"); |
|
1195 | 1196 |
break; |
1196 | 1197 |
|
1197 | 1198 |
case 0: |
... | ... |
@@ -23,6 +23,7 @@ |
23 | 23 |
** 08/05/2k4 - Now works as a charm :D |
24 | 24 |
** 09/05/2k4 - Moved code outta main(), got rid of globals for thread safety, added bound checking, minor cleaning |
25 | 25 |
** 04/06/2k4 - Now we handle 2B, 2D and 2E :D |
26 |
+** 28/08/2k4 - PE rebuild for nested packers |
|
26 | 27 |
*/ |
27 | 28 |
|
28 | 29 |
/* |
... | ... |
@@ -48,6 +49,131 @@ |
48 | 48 |
#include <string.h> |
49 | 49 |
|
50 | 50 |
#include "cltypes.h" |
51 |
+#include "others.h" |
|
52 |
+ |
|
53 |
+#define HEADERS "\ |
|
54 |
+\x4D\x5A\x90\x00\x02\x00\x00\x00\x04\x00\x0F\x00\xFF\xFF\x00\x00\ |
|
55 |
+\xB0\x00\x00\x00\x00\x00\x00\x00\x40\x00\x1A\x00\x00\x00\x00\x00\ |
|
56 |
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ |
|
57 |
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xD0\x00\x00\x00\ |
|
58 |
+\x0E\x1F\xB4\x09\xBA\x0D\x00\xCD\x21\xB4\x4C\xCD\x21\x54\x68\x69\ |
|
59 |
+\x73\x20\x66\x69\x6C\x65\x20\x77\x61\x73\x20\x63\x72\x65\x61\x74\ |
|
60 |
+\x65\x64\x20\x62\x79\x20\x43\x6C\x61\x6D\x41\x56\x20\x66\x6F\x72\ |
|
61 |
+\x20\x69\x6E\x74\x65\x72\x6E\x61\x6C\x20\x75\x73\x65\x20\x61\x6E\ |
|
62 |
+\x64\x20\x73\x68\x6F\x75\x6C\x64\x20\x6E\x6F\x74\x20\x62\x65\x20\ |
|
63 |
+\x72\x75\x6E\x2E\x0D\x0A\x43\x6C\x61\x6D\x41\x56\x20\x2D\x20\x41\ |
|
64 |
+\x20\x47\x50\x4C\x20\x76\x69\x72\x75\x73\x20\x73\x63\x61\x6E\x6E\ |
|
65 |
+\x65\x72\x20\x2D\x20\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\ |
|
66 |
+\x63\x6C\x61\x6D\x61\x76\x2E\x6E\x65\x74\x0D\x0A\x24\x00\x00\x00\ |
|
67 |
+" |
|
68 |
+ |
|
69 |
+#if WORDS_BIGENDIAN == 0 |
|
70 |
+#define EC32(v) (v) |
|
71 |
+#else |
|
72 |
+static inline uint32_t EC32(uint32_t v) |
|
73 |
+{ |
|
74 |
+ return ((v >> 24) | ((v & 0x00FF0000) >> 8) | ((v & 0x0000FF00) << 8) | (v << 24)); |
|
75 |
+} |
|
76 |
+#endif |
|
77 |
+ |
|
78 |
+#define cli_writeint32(offset,value) *(uint32_t *)(offset) = EC32(value) |
|
79 |
+ |
|
80 |
+/* PE from UPX */ |
|
81 |
+ |
|
82 |
+int pefromupx (char *src, char *dst, int *dsize, uint32_t ep, uint32_t upx0, uint32_t upx1, uint32_t magic) |
|
83 |
+{ |
|
84 |
+ char *imports, *sections, *pehdr, *newbuf; |
|
85 |
+ int sectcnt, upd=1, realstuffsz, align; |
|
86 |
+ int foffset=0xd0+0xf8; |
|
87 |
+ |
|
88 |
+ imports = dst + cli_readint32(src + ep - upx1 + magic); |
|
89 |
+ |
|
90 |
+ realstuffsz = imports-dst; |
|
91 |
+ |
|
92 |
+ if ( realstuffsz < 0 || realstuffsz > *dsize ) |
|
93 |
+ return 0; |
|
94 |
+ |
|
95 |
+ pehdr = imports; |
|
96 |
+ while (pehdr+7 < dst+*dsize && cli_readint32(pehdr)) { |
|
97 |
+ pehdr+=8; |
|
98 |
+ while(pehdr+1 < dst+*dsize && *pehdr) { |
|
99 |
+ pehdr++; |
|
100 |
+ while (pehdr+1 < dst+*dsize && *pehdr) |
|
101 |
+ pehdr++; |
|
102 |
+ pehdr++; |
|
103 |
+ } |
|
104 |
+ pehdr++; |
|
105 |
+ } |
|
106 |
+ |
|
107 |
+ pehdr+=4; |
|
108 |
+ if (pehdr+0xf8 > dst+*dsize) |
|
109 |
+ return 0; |
|
110 |
+ |
|
111 |
+ if ( cli_readint32(pehdr) != 0x4550 ) |
|
112 |
+ return 0; |
|
113 |
+ |
|
114 |
+ if (! (align = cli_readint32(pehdr+0x38))) |
|
115 |
+ return 0; |
|
116 |
+ |
|
117 |
+ sections = pehdr+0xf8; |
|
118 |
+ if ( ! (sectcnt = pehdr[6]+256*pehdr[7])) |
|
119 |
+ return 0; |
|
120 |
+ |
|
121 |
+ foffset+=0x28*sectcnt; |
|
122 |
+ |
|
123 |
+ if (pehdr + 0xf8 + 0x28*sectcnt >= dst + *dsize) |
|
124 |
+ return 0; |
|
125 |
+ |
|
126 |
+ for (upd = 0; upd <sectcnt ; upd++) { |
|
127 |
+ uint32_t vsize=cli_readint32(sections+8)-1; |
|
128 |
+ uint32_t rsize=cli_readint32(sections+16); |
|
129 |
+ uint32_t urva=cli_readint32(sections+12); |
|
130 |
+ |
|
131 |
+ vsize=(((vsize/0x1000)+1)*0x1000); /* FIXME: get bounds from header */ |
|
132 |
+ |
|
133 |
+ /* Within bounds ? */ |
|
134 |
+ if ( urva < upx0 || urva + vsize > upx0 + realstuffsz) |
|
135 |
+ return 0; |
|
136 |
+ |
|
137 |
+ /* Rsize -gt Vsize ? */ |
|
138 |
+ if ( rsize > vsize ) |
|
139 |
+ return 0; |
|
140 |
+ |
|
141 |
+ /* Am i been fooled? There are better ways ;) */ |
|
142 |
+ if ( rsize+4 < vsize && cli_readint32(dst+urva-upx0+rsize) ) |
|
143 |
+ return 0; |
|
144 |
+ |
|
145 |
+ cli_writeint32(sections+8, vsize); |
|
146 |
+ cli_writeint32(sections+20, foffset); |
|
147 |
+ foffset+=rsize; |
|
148 |
+ |
|
149 |
+ sections+=0x28; |
|
150 |
+ } |
|
151 |
+ |
|
152 |
+ cli_writeint32(pehdr+8, 0x4d414c43); |
|
153 |
+ |
|
154 |
+ if (!(newbuf = (char *) cli_malloc(foffset))) |
|
155 |
+ return 0; |
|
156 |
+ |
|
157 |
+ memcpy(newbuf, HEADERS, 0xd0); |
|
158 |
+ memcpy(newbuf+0xd0, pehdr,0xf8+0x28*sectcnt); |
|
159 |
+ sections = pehdr+0xf8; |
|
160 |
+ for (upd = 0; upd <sectcnt ; upd++) { |
|
161 |
+ memcpy(newbuf+cli_readint32(sections+20), dst+cli_readint32(sections+12)-upx0, cli_readint32(sections+16)); |
|
162 |
+ sections+=0x28; |
|
163 |
+ } |
|
164 |
+ |
|
165 |
+ /* CBA restoring the imports they'll look different from the originals anyway... */ |
|
166 |
+ /* ...and yeap i miss the icon too :P */ |
|
167 |
+ |
|
168 |
+ memcpy(dst, newbuf, foffset); |
|
169 |
+ *dsize = foffset; |
|
170 |
+ free(newbuf); |
|
171 |
+ |
|
172 |
+ cli_dbgmsg("UPX: PE structure rebuilt from compressed file\n"); |
|
173 |
+ return 1; |
|
174 |
+} |
|
175 |
+ |
|
51 | 176 |
|
52 | 177 |
/* [doubleebx] */ |
53 | 178 |
|
... | ... |
@@ -82,14 +208,14 @@ static int doubleebx(char *src, int32_t *myebx, int *scur, int ssize) |
82 | 82 |
|
83 | 83 |
/* [inflate] */ |
84 | 84 |
|
85 |
-int upx_inflate2b(char *src, int ssize, char *dst, int dsize) |
|
85 |
+int upx_inflate2b(char *src, int ssize, char *dst, int *dsize, uint32_t upx0, uint32_t upx1, uint32_t ep) |
|
86 | 86 |
{ |
87 | 87 |
int32_t backbytes, unp_offset = -1, myebx = 0; |
88 | 88 |
int scur=0, dcur=0, i, backsize,oob; |
89 | 89 |
|
90 | 90 |
while (1) { |
91 | 91 |
while ((oob = doubleebx(src, &myebx, &scur, ssize)) == 1) { |
92 |
- if (scur<0 || scur>=ssize || dcur<0 || dcur>=dsize) |
|
92 |
+ if (scur<0 || scur>=ssize || dcur<0 || dcur>=*dsize) |
|
93 | 93 |
return -1; |
94 | 94 |
dst[dcur++] = src[scur++]; |
95 | 95 |
} |
... | ... |
@@ -149,23 +275,31 @@ int upx_inflate2b(char *src, int ssize, char *dst, int dsize) |
149 | 149 |
backsize++; |
150 | 150 |
|
151 | 151 |
for (i = 0; i < backsize; i++) { |
152 |
- if (dcur+i<0 || dcur+i>=dsize || dcur+unp_offset+i<0 || dcur+unp_offset+i>=dsize) |
|
152 |
+ if (dcur+i<0 || dcur+i>=*dsize || dcur+unp_offset+i<0 || dcur+unp_offset+i>=*dsize) |
|
153 | 153 |
return -1; |
154 | 154 |
dst[dcur + i] = dst[dcur + unp_offset + i]; |
155 | 155 |
} |
156 | 156 |
dcur+=backsize; |
157 | 157 |
} |
158 |
+ |
|
159 |
+ |
|
160 |
+ if ( ep - upx1 + 0x14f <= ssize-5 && /* Wondering how we got so far?! */ |
|
161 |
+ src[ep - upx1 + 0x14f] == '\xe9' && /* JMP OldEip */ |
|
162 |
+ src[ep - upx1 + 0x106] == '\x8d' && /* lea edi, ... */ |
|
163 |
+ src[ep - upx1 + 0x107] == '\xbe' ) /* ... [esi + offset] */ |
|
164 |
+ return pefromupx (src, dst, dsize, ep, upx0, upx1, 0x108); |
|
165 |
+ |
|
158 | 166 |
return 0; |
159 | 167 |
} |
160 | 168 |
|
161 |
-int upx_inflate2d(char *src, int ssize, char *dst, int dsize) |
|
169 |
+int upx_inflate2d(char *src, int ssize, char *dst, int *dsize, uint32_t upx0, uint32_t upx1, uint32_t ep) |
|
162 | 170 |
{ |
163 | 171 |
int32_t backbytes, unp_offset = -1, myebx = 0; |
164 | 172 |
int scur=0, dcur=0, i, backsize, oob; |
165 | 173 |
|
166 | 174 |
while (1) { |
167 | 175 |
while ( (oob = doubleebx(src, &myebx, &scur, ssize)) == 1) { |
168 |
- if (scur<0 || scur>=ssize || dcur<0 || dcur>=dsize) |
|
176 |
+ if (scur<0 || scur>=ssize || dcur<0 || dcur>=*dsize) |
|
169 | 177 |
return -1; |
170 | 178 |
dst[dcur++] = src[scur++]; |
171 | 179 |
} |
... | ... |
@@ -231,16 +365,23 @@ int upx_inflate2d(char *src, int ssize, char *dst, int dsize) |
231 | 231 |
|
232 | 232 |
backsize++; |
233 | 233 |
for (i = 0; i < backsize; i++) { |
234 |
- if (dcur+i<0 || dcur+i>=dsize || dcur+unp_offset+i<0 || dcur+unp_offset+i>=dsize) |
|
234 |
+ if (dcur+i<0 || dcur+i>=*dsize || dcur+unp_offset+i<0 || dcur+unp_offset+i>=*dsize) |
|
235 | 235 |
return -1; |
236 | 236 |
dst[dcur + i] = dst[dcur + unp_offset + i]; |
237 | 237 |
} |
238 | 238 |
dcur+=backsize; |
239 | 239 |
} |
240 |
+ |
|
241 |
+ if ( ep - upx1 + 0x139 <= ssize-5 && /* Wondering how we got so far?! */ |
|
242 |
+ src[ep - upx1 + 0x139] == '\xe9' && /* JMP OldEip */ |
|
243 |
+ src[ep - upx1 + 0xe7] == '\x8d' && /* lea edi, ... */ |
|
244 |
+ src[ep - upx1 + 0xe8] == '\xbe' ) /* ... [esi + offset] */ |
|
245 |
+ return pefromupx (src, dst, dsize, ep, upx0, upx1, 0xe9); |
|
246 |
+ |
|
240 | 247 |
return 0; |
241 | 248 |
} |
242 | 249 |
|
243 |
-int upx_inflate2e(char *src, int ssize, char *dst, int dsize) |
|
250 |
+int upx_inflate2e(char *src, int ssize, char *dst, int *dsize, uint32_t upx0, uint32_t upx1, uint32_t ep) |
|
244 | 251 |
{ |
245 | 252 |
int32_t backbytes, unp_offset = -1, myebx = 0; |
246 | 253 |
int scur=0, dcur=0, i, backsize, oob; |
... | ... |
@@ -249,7 +390,7 @@ int upx_inflate2e(char *src, int ssize, char *dst, int dsize) |
249 | 249 |
while ( (oob = doubleebx(src, &myebx, &scur, ssize)) ) { |
250 | 250 |
if (oob == -1) |
251 | 251 |
return -1; |
252 |
- if (scur<0 || scur>=ssize || dcur<0 || dcur>=dsize) |
|
252 |
+ if (scur<0 || scur>=ssize || dcur<0 || dcur>=*dsize) |
|
253 | 253 |
return -1; |
254 | 254 |
dst[dcur++] = src[scur++]; |
255 | 255 |
} |
... | ... |
@@ -322,12 +463,18 @@ int upx_inflate2e(char *src, int ssize, char *dst, int dsize) |
322 | 322 |
|
323 | 323 |
backsize+=2; |
324 | 324 |
for (i = 0; i < backsize; i++) { |
325 |
- if (dcur+i<0 || dcur+i>=dsize || dcur+unp_offset+i<0 || dcur+unp_offset+i>=dsize) |
|
325 |
+ if (dcur+i<0 || dcur+i>=*dsize || dcur+unp_offset+i<0 || dcur+unp_offset+i>=*dsize) |
|
326 | 326 |
return -1; |
327 | 327 |
dst[dcur + i] = dst[dcur + unp_offset + i]; |
328 | 328 |
} |
329 | 329 |
dcur+=backsize; |
330 | 330 |
} |
331 |
+ |
|
332 |
+ if ( ep - upx1 + 0x145 <= ssize-5 && /* Wondering how we got so far?! */ |
|
333 |
+ src[ep - upx1 + 0x145] == '\xe9' && /* JMP OldEip */ |
|
334 |
+ src[ep - upx1 + 0xf3] == '\x8d' && /* lea edi, ... */ |
|
335 |
+ src[ep - upx1 + 0xf4] == '\xbe' ) /* ... [esi + offset] */ |
|
336 |
+ return pefromupx (src, dst, dsize, ep, upx0, upx1, 0xf5); |
|
337 |
+ |
|
331 | 338 |
return 0; |
332 | 339 |
} |
333 |
- |
... | ... |
@@ -19,8 +19,10 @@ |
19 | 19 |
#ifndef __UPX_H |
20 | 20 |
#define __UPX_H |
21 | 21 |
|
22 |
-int upx_inflate2b(char *, int , char *, int); |
|
23 |
-int upx_inflate2d(char *, int , char *, int); |
|
24 |
-int upx_inflate2e(char *, int , char *, int); |
|
22 |
+#include "cltypes.h" |
|
23 |
+ |
|
24 |
+int upx_inflate2b(char *, int, char *, int *, uint32_t, uint32_t, uint32_t); |
|
25 |
+int upx_inflate2d(char *, int, char *, int *, uint32_t, uint32_t, uint32_t); |
|
26 |
+int upx_inflate2e(char *, int, char *, int *, uint32_t, uint32_t, uint32_t); |
|
25 | 27 |
|
26 | 28 |
#endif |