... | ... |
@@ -784,18 +784,59 @@ uint32_t lzma_upack_esi_54(struct lzmastate *p, uint32_t old_eax, uint32_t *old_ |
784 | 784 |
return 0; |
785 | 785 |
} |
786 | 786 |
|
787 |
- |
|
787 |
+/** |
|
788 |
+ * @brief Unpack MEW 11 packed PE file |
|
789 |
+ * |
|
790 |
+ * @param src buffer to unpack |
|
791 |
+ * @param off offset of diff |
|
792 |
+ * @param ssize pe section size |
|
793 |
+ * @param dsize diff size |
|
794 |
+ * @param base OPTIONAL_HEADER32.ImageBase |
|
795 |
+ * @param vadd RVA of pe section |
|
796 |
+ * @param uselzma Bool - use LZMA |
|
797 |
+ * @param filedesc File descriptor |
|
798 |
+ * @return int Returns -1 on failure, 1 on success. |
|
799 |
+ */ |
|
788 | 800 |
int unmew11(char *src, uint32_t off, uint32_t ssize, uint32_t dsize, uint32_t base, uint32_t vadd, int uselzma, int filedesc) |
789 | 801 |
{ |
790 | 802 |
uint32_t entry_point, newedi, loc_ds=dsize, loc_ss=ssize; |
791 |
- char *source = src + dsize + off; |
|
792 |
- const char *lesi = source + 12; |
|
803 |
+ char *source = NULL; |
|
804 |
+ const char *lesi = NULL; |
|
793 | 805 |
char *ledi; |
794 | 806 |
const char *f1; |
795 | 807 |
char *f2; |
796 | 808 |
int i; |
797 | 809 |
struct cli_exe_section *section = NULL; |
798 |
- uint32_t vma = base + vadd, size_sum = ssize + dsize; |
|
810 |
+ uint32_t vma = base + vadd; |
|
811 |
+ uint32_t size_sum = ssize + dsize; |
|
812 |
+ |
|
813 |
+ /* Guard against integer overflows */ |
|
814 |
+ if (base + vadd < base) { |
|
815 |
+ cli_dbgmsg("MEW: base (%08x) + PE section RVA (%08x) exceeds max size of unsigned int (%08x)\n", |
|
816 |
+ base, vadd, UINT32_MAX); |
|
817 |
+ return -1; |
|
818 |
+ } |
|
819 |
+ if (ssize + dsize < ssize) { |
|
820 |
+ cli_dbgmsg("MEW: section size (%08x) + diff size (%08x) exceeds max size of unsigned int (%08x)\n", |
|
821 |
+ ssize, dsize, UINT32_MAX); |
|
822 |
+ return -1; |
|
823 |
+ } |
|
824 |
+ if (((size_t)(src + off) < (size_t)(src)) || |
|
825 |
+ ((size_t)(src + off) < (size_t)(off))) |
|
826 |
+ { |
|
827 |
+ cli_dbgmsg("MEW: Buffer pointer (%08zx) + offset (%08zx) exceeds max size of pointer (%08lx)\n", |
|
828 |
+ (size_t)src, (size_t)off, SIZE_MAX); |
|
829 |
+ return -1; |
|
830 |
+ } |
|
831 |
+ |
|
832 |
+ /* Ensure that off + required data exists within buffer */ |
|
833 |
+ if (!CLI_ISCONTAINED(src, size_sum, src + off, 12)) { |
|
834 |
+ cli_dbgmsg("MEW: Data reference exceeds size of provided buffer.\n"); |
|
835 |
+ return -1; |
|
836 |
+ } |
|
837 |
+ |
|
838 |
+ source = src + dsize + off; |
|
839 |
+ lesi = source + 12; |
|
799 | 840 |
|
800 | 841 |
entry_point = cli_readint32(source + 4); |
801 | 842 |
newedi = cli_readint32(source + 8); |
... | ... |
@@ -47,6 +47,7 @@ |
47 | 47 |
|
48 | 48 |
#include <stdio.h> |
49 | 49 |
#include <stdlib.h> |
50 |
+#include <stdint.h> |
|
50 | 51 |
|
51 | 52 |
#if HAVE_STRING_H |
52 | 53 |
#include <string.h> |
... | ... |
@@ -3899,7 +3900,10 @@ int cli_scanpe(cli_ctx *ctx) |
3899 | 3899 |
else |
3900 | 3900 |
cli_dbgmsg("MEW: Win9x compatibility was NOT set!\n"); |
3901 | 3901 |
|
3902 |
- if((offdiff = cli_readint32(tbuff+1) - EC32(optional_hdr32.ImageBase)) <= exe_sections[i + 1].rva || offdiff >= exe_sections[i + 1].rva + exe_sections[i + 1].raw - 4) { |
|
3902 |
+ offdiff = cli_readint32(tbuff+1) - EC32(optional_hdr32.ImageBase); |
|
3903 |
+ if ((offdiff <= exe_sections[i + 1].rva) || |
|
3904 |
+ (offdiff >= exe_sections[i + 1].rva + exe_sections[i + 1].raw - 4)) |
|
3905 |
+ { |
|
3903 | 3906 |
cli_dbgmsg("MEW: ESI is not in proper section\n"); |
3904 | 3907 |
break; |
3905 | 3908 |
} |
... | ... |
@@ -3914,6 +3918,18 @@ int cli_scanpe(cli_ctx *ctx) |
3914 | 3914 |
ssize = exe_sections[i + 1].vsz; |
3915 | 3915 |
dsize = exe_sections[i].vsz; |
3916 | 3916 |
|
3917 |
+ /* Guard against integer overflow */ |
|
3918 |
+ if ((ssize + dsize < ssize) || (ssize + dsize < dsize)) { |
|
3919 |
+ cli_dbgmsg("MEW: section size (%08x) + diff size (%08x) exceeds max size of unsigned int (%08x)\n", ssize, dsize, UINT32_MAX); |
|
3920 |
+ break; |
|
3921 |
+ } |
|
3922 |
+ |
|
3923 |
+ /* Verify that offdiff does not exceed the ssize + sdiff */ |
|
3924 |
+ if (offdiff >= ssize + dsize) { |
|
3925 |
+ cli_dbgmsg("MEW: offdiff (%08x) exceeds section size + diff size (%08x)\n", offdiff, ssize + dsize); |
|
3926 |
+ break; |
|
3927 |
+ } |
|
3928 |
+ |
|
3917 | 3929 |
cli_dbgmsg("MEW: ssize %08x dsize %08x offdiff: %08x\n", ssize, dsize, offdiff); |
3918 | 3930 |
|
3919 | 3931 |
CLI_UNPSIZELIMITS("MEW", MAX(ssize, dsize)); |