Browse code

Stack protector support.

Török Edvin authored on 2009/12/18 21:17:50
Showing 11 changed files
... ...
@@ -139,8 +139,6 @@ int main(int argc, char *argv[])
139 139
 	exit(1);
140 140
     }
141 141
     if(optget(opts, "version")->enabled) {
142
-	char versions[] = "--version";
143
-	char* argvx[] = {argv[0], versions,NULL};
144 142
 	printf("Clam AntiVirus Bytecode Testing Tool %s\n", get_version());
145 143
 	cl_init(CL_INIT_DEFAULT);
146 144
 	cli_bytecode_printversion();
... ...
@@ -265,7 +263,6 @@ int main(int argc, char *argv[])
265 265
 	funmap(map);
266 266
     }
267 267
 
268
-
269 268
     rc = cli_bytecode_run(&bcs, bc, ctx);
270 269
     if (rc != CL_SUCCESS) {
271 270
 	fprintf(stderr,"Unable to run bytecode: %s\n", cl_strerror(rc));
... ...
@@ -1081,10 +1081,16 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char
1081 1081
 			(1ull<<inst.u.cast.mask)-1 :
1082 1082
 			~0ull;
1083 1083
 		break;
1084
+	    case OP_BC_GEP1:
1085
+	    case OP_BC_GEPZ:
1086
+		inst.u.three[0] = readNumber(buffer, &offset, len, &ok);
1087
+		inst.u.three[1] = readOperand(bcfunc, buffer, &offset, len, &ok);
1088
+		inst.u.three[2] = readOperand(bcfunc, buffer, &offset, len, &ok);
1089
+		break;
1084 1090
 	    case OP_BC_GEPN:
1085 1091
 		numOp = readFixedNumber(buffer, &offset, len, &ok, 1);
1086 1092
 		if (ok) {
1087
-		    inst.u.ops.numOps = numOp+1;
1093
+		    inst.u.ops.numOps = numOp+2;
1088 1094
 		    inst.u.ops.opsizes = NULL;
1089 1095
 		    inst.u.ops.ops = cli_calloc(numOp, sizeof(*inst.u.ops.ops));
1090 1096
 		    if (!inst.u.ops.ops) {
... ...
@@ -1092,7 +1098,7 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char
1092 1092
 			return CL_EMEM;
1093 1093
 		    }
1094 1094
 		    inst.u.ops.ops[0] = readNumber(buffer, &offset, len, &ok);
1095
-		    for (i=1;i<numOp+1;i++)
1095
+		    for (i=1;i<numOp+2;i++)
1096 1096
 			inst.u.ops.ops[i] = readOperand(bcfunc, buffer, &offset, len, &ok);
1097 1097
 		}
1098 1098
 		break;
... ...
@@ -1548,6 +1554,7 @@ static int cli_bytecode_prepare_interpreter(struct cli_bc *bc)
1548 1548
 		    MAP(inst->u.unaryop);
1549 1549
 		    break;
1550 1550
 		case OP_BC_GEP1:
1551
+		case OP_BC_GEPZ:
1551 1552
 		    //three[0] is the type
1552 1553
 		    MAP(inst->u.three[1]);
1553 1554
 		    MAP(inst->u.three[2]);
... ...
@@ -76,15 +76,23 @@
76 76
 #include "bytecode.h"
77 77
 #include "bytecode_priv.h"
78 78
 #include "type_desc.h"
79
+extern "C" {
80
+#include "md5.h"
81
+}
79 82
 
80 83
 #define MODULE "libclamav JIT: "
81 84
 
85
+extern "C" unsigned int cli_rndnum(unsigned int max);
82 86
 using namespace llvm;
83 87
 typedef DenseMap<const struct cli_bc_func*, void*> FunctionMapTy;
84 88
 struct cli_bcengine {
85 89
     ExecutionEngine *EE;
86 90
     LLVMContext Context;
87 91
     FunctionMapTy compiledFunctions;
92
+    union {
93
+	unsigned char b[16];
94
+	void* align;/* just to align field to ptr */
95
+    } guard;
88 96
 };
89 97
 
90 98
 namespace {
... ...
@@ -101,6 +109,12 @@ static void NORETURN jit_exception_handler(void)
101 101
     longjmp(*const_cast<jmp_buf*>(ExceptionReturn.get()), 1);
102 102
 }
103 103
 
104
+static void NORETURN jit_ssp_handler(void)
105
+{
106
+    errs() << "Bytecode JIT: *** stack smashing detected, bytecode aborted\n";
107
+    jit_exception_handler();
108
+}
109
+
104 110
 void llvm_error_handler(void *user_data, const std::string &reason)
105 111
 {
106 112
     // Output it to stderr, it might exceed the 1k/4k limit of cli_errmsg
... ...
@@ -471,6 +485,18 @@ public:
471 471
 	return N;
472 472
     }
473 473
 
474
+    void AddStackProtect(Function *F)
475
+    {
476
+	BasicBlock &BB = F->getEntryBlock();
477
+	if (isa<AllocaInst>(BB.begin())) {
478
+	    // Have an alloca -> some instruction uses its address otherwise
479
+	    // mem2reg would have converted it to an SSA register.
480
+	    // Enable stack protector for this function.
481
+	    F->addFnAttr(Attribute::StackProtect);
482
+	    F->addFnAttr(Attribute::StackProtectReq);
483
+	}
484
+    }
485
+
474 486
     bool generate() {
475 487
 	TypeMap = new LLVMTypeMapper(Context, bc->types + 4, bc->num_types - 5);
476 488
 	for (unsigned i=0;i<bc->dbgnode_cnt;i++) {
... ...
@@ -493,6 +519,7 @@ public:
493 493
 	FHandler->addFnAttr(Attribute::NoInline);
494 494
 	EE->addGlobalMapping(FHandler, (void*)(intptr_t)jit_exception_handler);
495 495
 
496
+
496 497
 	std::vector<const Type*> args;
497 498
 	args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context)));
498 499
 	args.push_back(Type::getInt8Ty(Context));
... ...
@@ -683,6 +710,7 @@ public:
683 683
 			case OP_BC_SEXT:
684 684
 			case OP_BC_TRUNC:
685 685
 			case OP_BC_GEP1:
686
+			case OP_BC_GEPZ:
686 687
 			case OP_BC_GEPN:
687 688
 			case OP_BC_STORE:
688 689
 			case OP_BC_COPY:
... ...
@@ -892,6 +920,17 @@ public:
892 892
 				return false;
893 893
 			    break;
894 894
 			}
895
+			case OP_BC_GEPZ:
896
+			{
897
+			    Value *Ops[2];
898
+			    Ops[0] = ConstantInt::get(Type::getInt32Ty(Context), 0);
899
+			    const Type *SrcTy = mapType(inst->u.three[0]);
900
+			    Value *V = convertOperand(func, SrcTy, inst->u.three[1]);
901
+			    Ops[1] = convertOperand(func, I32Ty, inst->u.three[2]);
902
+			    if (!createGEP(inst->dest, V, Ops, Ops+2))
903
+				return false;
904
+			    break;
905
+			}
895 906
 			case OP_BC_GEPN:
896 907
 			{
897 908
 			    std::vector<Value*> Idxs;
... ...
@@ -995,6 +1034,7 @@ public:
995 995
 		return false;
996 996
 	    }
997 997
 	    PM.run(*F);
998
+	    AddStackProtect(F);
998 999
 	    delete [] Values;
999 1000
 	    delete [] BB;
1000 1001
 	}
... ...
@@ -1068,6 +1108,20 @@ int cli_vm_execute_jit(const struct cli_all_bc *bcs, struct cli_bc_ctx *ctx,
1068 1068
     return CL_EBYTECODE;
1069 1069
 }
1070 1070
 
1071
+static unsigned char name_salt[16] = { 16, 38, 97, 12, 8, 4, 72, 196, 217, 144, 33, 124, 18, 11, 17, 253 };
1072
+static void setGuard(unsigned char* guardbuf)
1073
+{
1074
+    cli_md5_ctx ctx;
1075
+    char salt[48];
1076
+    memcpy(salt, name_salt, 16);
1077
+    for(unsigned i = 16; i < 48; i++)
1078
+	salt[i] = cli_rndnum(255);
1079
+
1080
+    cli_md5_init(&ctx);
1081
+    cli_md5_update(&ctx, salt, 48);
1082
+    cli_md5_final(guardbuf, &ctx);
1083
+}
1084
+
1071 1085
 int cli_bytecode_prepare_jit(struct cli_all_bc *bcs)
1072 1086
 {
1073 1087
   if (!bcs->engine)
... ...
@@ -1092,7 +1146,7 @@ int cli_bytecode_prepare_jit(struct cli_all_bc *bcs)
1092 1092
 	EngineBuilder builder(MP);
1093 1093
 	builder.setErrorStr(&ErrorMsg);
1094 1094
 	builder.setEngineKind(EngineKind::JIT);
1095
-	builder.setOptLevel(CodeGenOpt::Aggressive);
1095
+	builder.setOptLevel(CodeGenOpt::Default);
1096 1096
 	ExecutionEngine *EE = bcs->engine->EE = builder.create();
1097 1097
 	if (!EE) {
1098 1098
 	    if (!ErrorMsg.empty())
... ...
@@ -1141,6 +1195,23 @@ int cli_bytecode_prepare_jit(struct cli_all_bc *bcs)
1141 1141
 	    apiFuncs[i] = F;
1142 1142
 	}
1143 1143
 
1144
+	// stack protector
1145
+	FunctionType *FTy = FunctionType::get(Type::getVoidTy(M->getContext()),
1146
+						    false);
1147
+	GlobalVariable *Guard = new GlobalVariable(*M, PointerType::getUnqual(Type::getInt8Ty(M->getContext())),
1148
+						    true, GlobalValue::InternalLinkage, 0, "__stack_chk_guard"); 
1149
+	unsigned plus = 0;
1150
+	if (2*sizeof(void*) <= 16 && cli_rndnum(2)==2) {
1151
+	    plus = sizeof(void*);
1152
+	}
1153
+	EE->addGlobalMapping(Guard, (void*)(&bcs->engine->guard.b[plus]));
1154
+	setGuard(bcs->engine->guard.b);
1155
+	bcs->engine->guard.b[plus+sizeof(void*)-1] = 0x00;
1156
+//	printf("%p\n", *(void**)(&bcs->engine->guard.b[plus]));
1157
+	Function *SFail = Function::Create(FTy, Function::ExternalLinkage,
1158
+					      "__stack_chk_fail", M);
1159
+	EE->addGlobalMapping(SFail, (void*)(intptr_t)jit_ssp_handler);
1160
+
1144 1161
 	for (unsigned i=0;i<bcs->count;i++) {
1145 1162
 	    const struct cli_bc *bc = &bcs->all_bcs[i];
1146 1163
 	    if (bc->state == bc_skip)
... ...
@@ -28,7 +28,7 @@ struct bytecode_metadata {
28 28
   char *targetExclude;
29 29
 };
30 30
 
31
-#define BC_FUNC_LEVEL 3
31
+#define BC_FUNC_LEVEL 4
32 32
 #define BC_HEADER "ClamBC"
33 33
 
34 34
 enum bc_opcode {
... ...
@@ -70,6 +70,7 @@ enum bc_opcode {
70 70
   OP_BC_CALL_API,
71 71
   OP_BC_COPY,
72 72
   OP_BC_GEP1,
73
+  OP_BC_GEPZ,
73 74
   OP_BC_GEPN,
74 75
   OP_BC_STORE,
75 76
   OP_BC_LOAD,
... ...
@@ -98,8 +99,8 @@ static const unsigned char operand_counts[] = {
98 98
   0, 0,
99 99
   /* OP_BC_COPY */
100 100
   2,
101
-  /* OP_BC_GEP1, OP_BC_GEPN, OP_BC_STORE, OP_BC_LOAD*/
102
-  3, 0, 2, 1,
101
+  /* OP_BC_GEP1, OP_BC_GEPZ, OP_BC_GEPN, OP_BC_STORE, OP_BC_LOAD*/
102
+  3, 3, 0, 2, 1,
103 103
   /* OP_MEM* */
104 104
   3, 3, 3, 3,
105 105
   /* OP_BC_ISBIGENDIAN */
... ...
@@ -1984,7 +1984,7 @@ int cli_scanpe(cli_ctx *ctx, icon_groupset *iconset)
1984 1984
 
1985 1985
 
1986 1986
     /* yC 1.3 & variants */
1987
-    if((DCONF & PE_CONF_YC) && nsections > 1 &&
1987
+    if((0 & DCONF & PE_CONF_YC) && nsections > 1 &&
1988 1988
        (EC32(optional_hdr32.AddressOfEntryPoint) == exe_sections[nsections - 1].rva + 0x60)) {
1989 1989
 
1990 1990
 	uint32_t ecx = 0;
... ...
@@ -1,4 +1,4 @@
1
-ClamBCac`|``````|`agafp`clamcoincidencejb:82
1
+ClamBCad`|``````|`agafp`clamcoincidencejb:82
2 2
 
3 3
 Tedaaa`aacb`bb`bb`b
4 4
 Eabaaabbfd|afdgefcgdgac``
... ...
@@ -1,10 +1,10 @@
1
-ClamBCac`|``````|`akafp`clamcoincidencejb:86
1
+ClamBCad`|``````|`akafp`clamcoincidencejb:83
2 2
 
3 3
 Tedcaabfdebedebfdaaa`aacb`bbfdb`baacb`bb`bb`b
4 4
 Eababaabid|afdgefcgdg`c``abbjd|afdgefcgdgac``
5 5
 G`aa`@`
6 6
 A`b`bLahbedabgd```b`b`aa`b`b`aa`b`b`Fajac
7
-Bbgdaadbcbfd`@d@d``eb`aab`bacabbabHonnkm``odHm``oonnkdaaadeab`bacHhgfedcbadTaaadaaab
7
+Bbgdaadbbfd`@d``fb`aab`bacabbabHonnkm``odHm``oonnkdaaadeab`bacHhgfedcbadTaaadaaab
8 8
 Bb`baeabbaa`Honnkmjnmdaaafeab`baeHhgfedcbadb`bagoaafDm``odDmjnmdTcab`bag
9 9
 BTcab`bDmjnmdE
10 10
 Aab`bLabah`aa`b`b`Facaa
... ...
@@ -1,4 +1,4 @@
1
-ClamBCac`|``````|`afbbep`clamcoincidencejb:418
1
+ClamBCad`|``````|`afbbep`clamcoincidencejb:418
2 2
 
3 3
 Tedaaa`
4 4
 E``
... ...
@@ -1,4 +1,4 @@
1
-ClamBCac`|``````|`afabp`clamcoincidencejb:23
1
+ClamBCad`|``````|`afabp`clamcoincidencejb:23
2 2
 
3 3
 Tedaaa`
4 4
 E``
... ...
@@ -1,11 +1,11 @@
1
-ClamBCac`|``c``a```|`bjaabp`clamcoincidencejb:326
1
+ClamBCad`|``c``a```|`bjaabp`clamcoincidencejb:326
2 2
 Trojan.Foo.{A,B};Target:1;(((0|1|2)=42,2)|(3=10));EP+0:aabb;ffff;aaccee;f00d;dead
3 3
 Tedebieebheebgeebfeebeeebdeebbeebaeebadebcdaaa`aacb`bbadb`bdb`db`bcajbadbcebadbcebadbcebadbcebadbcecaab`bdagahdaeahdajahdabbaddabahdakah
4 4
 Eafaaafb`e|amcgefdgfgifbgegcgnfafmfef``
5 5
 Gd```hbia`@`bieBdeBbgBofBjfBafBnfBnbBfdBofBof@`bheBad@`bheBbd@`bge@Ab@Ac`b`aAa`b`aC``a`bfeBedB`eBkbB`cBjcBafBafBbfBbf@`beeBffBffBffBff@`beeBffB`cB`cBdf@`bdeBafBafBcfBcfBefBef@`beeBdfBefBafBdf@`bbe@Ag@@AhAa@AiAc@AjAb@AkAd`bad@Ab`bad@Ac`bad@Ag`bad@Ah`bad@Ai`bad@Aj`bad@Ak`bcdAdD```h`bcdAcD```h`bcdAbD```h`bcdAaD```h`bcd@D```h`
6 6
 A`b`bLaeb`b`aa`aa`bad`b`b`Fahac
7
-Bb`b`fbBda`aaaagab`b`AadTaaaaaaab
7
+Bb`b`gbBda`aaaagab`b`AadTaaaaaaab
8 8
 Baaabeab`b`AbdbadacoaabAm`An`b`badabbafac@dTcab`b@d
9 9
 BTcab`b@dE
10 10
 A`aaLbcab`b`b`b`b`b`b`b`b`b`aa`aa`aa`aa`b`b`b`b`b`b`b`b`b`b`aa`aa`b`b`aa`aa`Fbdaaa
11
-Bb`b`fbBha`b`baafbBga`b`babfbBfa`b`baca`aa`b`bada`acabaaaeeab`badBjbdaaaffab`bab@daaagfab`baa@daaahfab`b`@db`bai`aafb`baj`aagb`bak`aahb`bala`ajakb`bama`alaiaaaneab`bamAbdaaaok`anaeb`bb`afbBea`aabaaeab`bb`aAjdaabbal`aobaaTcaaabbaE
11
+Bb`b`gbBha`b`baagbBga`b`babgbBfa`b`baca`aa`b`bada`acabaaaeeab`badBjbdaaaffab`bab@daaagfab`baa@daaahfab`b`@db`bai`aafb`baj`aagb`bak`aahb`bala`ajakb`bama`alaiaaaneab`bamAbdaaaok`anaeb`bb`agbBea`aabaaeab`bb`aAjdaabbal`aobaaTcaaabbaE
... ...
@@ -1,4 +1,4 @@
1
-ClamBCac`|``````|`afaap`clamcoincidencejb:20
1
+ClamBCad`|``````|`afaap`clamcoincidencejb:20
2 2
 
3 3
 Tedaaa`
4 4
 E``