Browse code

bb12170: Added pointer arithmetic guards to PE MEW unpacking code.

Micah Snyder authored on 2018/09/09 23:00:12
Showing 2 changed files
... ...
@@ -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));