Browse code

attempt to rebuild PE structure from UPX compressed files

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
Showing 4 changed files
... ...
@@ -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