├── ClassicalUseAfterFreePatternMatching ├── Taint.cpp ├── Taint.cpp.old ├── crackme ├── crackme.c ├── file.txt ├── makefile ├── makefile.rules ├── pin.log ├── pintool.log ├── test ├── test.c ├── testcpp └── testcpp.cpp ├── ConcolicExecution ├── ConcolicExecution.cpp ├── compile.sh ├── crackme1 ├── crackme1.c ├── crackme2 ├── crackme2.c ├── crackme3 ├── crackme3.c ├── ex ├── ex.cpp ├── makefile ├── makefile.rules ├── none ├── pin.log ├── pintool.log └── serial.txt ├── FormatStringDetection ├── file.txt ├── frmtstr.cpp ├── makefile ├── makefile.rules └── test.c ├── InMemoryFuzzing ├── InMemoryFuzzing.cpp ├── dump ├── makefile ├── makefile.rules ├── pin.log ├── pintool.log ├── test └── test.c ├── LoopDetectionInstCounter ├── loop.cpp ├── makefile ├── makefile.rules ├── output_loop_detection.txt ├── test └── test.c ├── ObsoleteStackFrameAccessDetection ├── Taint.cpp ├── crackme ├── crackme.c ├── file.txt ├── makefile ├── makefile.rules ├── out ├── pin.log ├── pintool.log ├── test └── test.c ├── OverflowDetection ├── OverflowDetection.cpp ├── makefile ├── makefile.rules ├── test ├── test.c ├── test1 ├── test1.c ├── testcpp └── testcpp.cpp ├── PointerWithoutCheckDetection ├── Taint.cpp ├── crackme ├── crackme.c ├── file.txt ├── makefile ├── makefile.rules ├── out ├── output_id.txt ├── pin.log ├── pintool.log ├── test ├── test.c └── test2.c ├── README.rst ├── TaintAnalysis ├── SimpleTaintMemoryArea │ ├── Taint.cpp │ ├── crackme │ ├── crackme.c │ ├── file.txt │ ├── makefile │ ├── makefile.rules │ ├── pin.log │ ├── pintool.log │ ├── serial.txt │ ├── test │ ├── test.c │ ├── test2 │ └── test2.c ├── SpreadTheTaintAndFollowYourData │ ├── Taint.cpp │ ├── crackme │ ├── crackme.c │ ├── file.txt │ ├── makefile │ ├── makefile.rules │ ├── out │ ├── pin.log │ ├── pintool.log │ ├── test │ └── test.c └── SpreadTheTaintInMemoryAndRegisters │ ├── Taint.cpp │ ├── crackme │ ├── crackme.c │ ├── file.txt │ ├── makefile │ ├── makefile.rules │ ├── out │ ├── pin.log │ ├── pintool.log │ ├── serial.txt │ ├── test │ ├── test.c │ ├── test2 │ └── test2.c └── Talks ├── SSTIC-2015 ├── SSTIC_2015_detailed_version_Triton_Concolic_Execution_FrameWork_FSaudel_JSalwan.pdf └── SSTIC_2015_light_version_Triton_Concolic_Execution_FrameWork_FSaudel_JSalwan.pdf ├── SecurityDayLille-2015 ├── README.rst └── SecurityDay2015_dynamic_symbolic_execution_Jonathan_Salwan.pdf └── StHack-2015 ├── README.rst └── StHack2015_Dynamic_Behavior_Analysis_using_Binary_Instrumentation_Jonathan_Salwan.pdf /ClassicalUseAfterFreePatternMatching/Taint.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Jonathan Salwan - Copyright (C) 2013-08 3 | // 4 | // http://shell-storm.org 5 | // http://twitter.com/JonathanSalwan 6 | // 7 | // Note: Example 5 - http://shell-storm.org/blog/Taint-analysis-with-Pin/ 8 | // Detect the classical use after free vulnerability 9 | // 10 | 11 | #include "pin.H" 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define LOCKED 1 18 | #define UNLOCKED !LOCKED 19 | 20 | #define ALLOCATE 1 21 | #define FREE !ALLOCATE 22 | 23 | static size_t lastSize; 24 | 25 | struct mallocArea 26 | { 27 | UINT64 base; 28 | UINT64 size; 29 | BOOL status; 30 | }; 31 | 32 | UINT32 lockTaint = LOCKED; 33 | 34 | std::list addressTainted; 35 | std::list regsTainted; 36 | std::list mallocAreaList; 37 | 38 | INT32 Usage() 39 | { 40 | std::cerr << "Ex 5" << std::endl; 41 | return -1; 42 | } 43 | 44 | BOOL checkAlreadyRegTainted(REG reg) 45 | { 46 | list::iterator i; 47 | 48 | for(i = regsTainted.begin(); i != regsTainted.end(); i++){ 49 | if (*i == reg){ 50 | return true; 51 | } 52 | } 53 | return false; 54 | } 55 | 56 | VOID removeMemTainted(UINT64 addr) 57 | { 58 | addressTainted.remove(addr); 59 | std::cout << std::hex << "\t\t\t" << addr << " is now freed" << std::endl; 60 | } 61 | 62 | VOID addMemTainted(UINT64 addr) 63 | { 64 | addressTainted.push_back(addr); 65 | std::cout << std::hex << "\t\t\t" << addr << " is now tainted" << std::endl; 66 | } 67 | 68 | BOOL taintReg(REG reg) 69 | { 70 | if (checkAlreadyRegTainted(reg) == true){ 71 | std::cout << "\t\t\t" << REG_StringShort(reg) << " is already tainted" << std::endl; 72 | return false; 73 | } 74 | 75 | switch(reg){ 76 | 77 | case REG_RAX: regsTainted.push_front(REG_RAX); 78 | case REG_EAX: regsTainted.push_front(REG_EAX); 79 | case REG_AX: regsTainted.push_front(REG_AX); 80 | case REG_AH: regsTainted.push_front(REG_AH); 81 | case REG_AL: regsTainted.push_front(REG_AL); 82 | break; 83 | 84 | case REG_RBX: regsTainted.push_front(REG_RBX); 85 | case REG_EBX: regsTainted.push_front(REG_EBX); 86 | case REG_BX: regsTainted.push_front(REG_BX); 87 | case REG_BH: regsTainted.push_front(REG_BH); 88 | case REG_BL: regsTainted.push_front(REG_BL); 89 | break; 90 | 91 | case REG_RCX: regsTainted.push_front(REG_RCX); 92 | case REG_ECX: regsTainted.push_front(REG_ECX); 93 | case REG_CX: regsTainted.push_front(REG_CX); 94 | case REG_CH: regsTainted.push_front(REG_CH); 95 | case REG_CL: regsTainted.push_front(REG_CL); 96 | break; 97 | 98 | case REG_RDX: regsTainted.push_front(REG_RDX); 99 | case REG_EDX: regsTainted.push_front(REG_EDX); 100 | case REG_DX: regsTainted.push_front(REG_DX); 101 | case REG_DH: regsTainted.push_front(REG_DH); 102 | case REG_DL: regsTainted.push_front(REG_DL); 103 | break; 104 | 105 | case REG_RDI: regsTainted.push_front(REG_RDI); 106 | case REG_EDI: regsTainted.push_front(REG_EDI); 107 | case REG_DI: regsTainted.push_front(REG_DI); 108 | case REG_DIL: regsTainted.push_front(REG_DIL); 109 | break; 110 | 111 | case REG_RSI: regsTainted.push_front(REG_RSI); 112 | case REG_ESI: regsTainted.push_front(REG_ESI); 113 | case REG_SI: regsTainted.push_front(REG_SI); 114 | case REG_SIL: regsTainted.push_front(REG_SIL); 115 | break; 116 | 117 | default: 118 | std::cout << "\t\t\t" << REG_StringShort(reg) << " can't be tainted" << std::endl; 119 | return false; 120 | } 121 | std::cout << "\t\t\t" << REG_StringShort(reg) << " is now tainted" << std::endl; 122 | return true; 123 | } 124 | 125 | BOOL removeRegTainted(REG reg) 126 | { 127 | switch(reg){ 128 | 129 | case REG_RAX: regsTainted.remove(REG_RAX); 130 | case REG_EAX: regsTainted.remove(REG_EAX); 131 | case REG_AX: regsTainted.remove(REG_AX); 132 | case REG_AH: regsTainted.remove(REG_AH); 133 | case REG_AL: regsTainted.remove(REG_AL); 134 | break; 135 | 136 | case REG_RBX: regsTainted.remove(REG_RBX); 137 | case REG_EBX: regsTainted.remove(REG_EBX); 138 | case REG_BX: regsTainted.remove(REG_BX); 139 | case REG_BH: regsTainted.remove(REG_BH); 140 | case REG_BL: regsTainted.remove(REG_BL); 141 | break; 142 | 143 | case REG_RCX: regsTainted.remove(REG_RCX); 144 | case REG_ECX: regsTainted.remove(REG_ECX); 145 | case REG_CX: regsTainted.remove(REG_CX); 146 | case REG_CH: regsTainted.remove(REG_CH); 147 | case REG_CL: regsTainted.remove(REG_CL); 148 | break; 149 | 150 | case REG_RDX: regsTainted.remove(REG_RDX); 151 | case REG_EDX: regsTainted.remove(REG_EDX); 152 | case REG_DX: regsTainted.remove(REG_DX); 153 | case REG_DH: regsTainted.remove(REG_DH); 154 | case REG_DL: regsTainted.remove(REG_DL); 155 | break; 156 | 157 | case REG_RDI: regsTainted.remove(REG_RDI); 158 | case REG_EDI: regsTainted.remove(REG_EDI); 159 | case REG_DI: regsTainted.remove(REG_DI); 160 | case REG_DIL: regsTainted.remove(REG_DIL); 161 | break; 162 | 163 | case REG_RSI: regsTainted.remove(REG_RSI); 164 | case REG_ESI: regsTainted.remove(REG_ESI); 165 | case REG_SI: regsTainted.remove(REG_SI); 166 | case REG_SIL: regsTainted.remove(REG_SIL); 167 | break; 168 | 169 | default: 170 | return false; 171 | } 172 | std::cout << "\t\t\t" << REG_StringShort(reg) << " is now freed" << std::endl; 173 | return true; 174 | } 175 | 176 | VOID ReadMem(UINT64 insAddr, std::string insDis, UINT32 opCount, REG reg_r, UINT64 memOp, UINT64 sp) 177 | { 178 | list::iterator i; 179 | list::iterator i2; 180 | UINT64 addr = memOp; 181 | 182 | if (opCount != 2) 183 | return; 184 | 185 | for(i2 = mallocAreaList.begin(); i2 != mallocAreaList.end(); i2++){ 186 | if (addr >= i2->base && addr < (i2->base + i2->size) && i2->status == FREE){ 187 | std::cout << std::hex << "[UAF in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 188 | return; 189 | } 190 | } 191 | 192 | for(i = addressTainted.begin(); i != addressTainted.end(); i++){ 193 | if (addr == *i){ 194 | std::cout << std::hex << "[READ in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 195 | taintReg(reg_r); 196 | 197 | if (sp > addr && addr > 0x700000000000) 198 | std::cout << std::hex << "[UAF in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 199 | 200 | return; 201 | } 202 | } 203 | if (checkAlreadyRegTainted(reg_r)){ 204 | std::cout << std::hex << "[READ in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 205 | removeRegTainted(reg_r); 206 | } 207 | } 208 | 209 | VOID WriteMem(UINT64 insAddr, std::string insDis, UINT32 opCount, REG reg_r, UINT64 memOp, UINT64 sp) 210 | { 211 | list::iterator i; 212 | list::iterator i2; 213 | UINT64 addr = memOp; 214 | 215 | if (opCount != 2) 216 | return; 217 | 218 | for(i2 = mallocAreaList.begin(); i2 != mallocAreaList.end(); i2++){ 219 | if (addr >= i2->base && addr < (i2->base + i2->size) && i2->status == FREE){ 220 | std::cout << std::hex << "[UAF in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 221 | return; 222 | } 223 | } 224 | 225 | for(i = addressTainted.begin(); i != addressTainted.end(); i++){ 226 | if (addr == *i){ 227 | std::cout << std::hex << "[WRITE in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 228 | if (!REG_valid(reg_r) || !checkAlreadyRegTainted(reg_r)) 229 | removeMemTainted(addr); 230 | 231 | if (sp > addr && addr > 0x700000000000) 232 | std::cout << std::hex << "[UAF in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 233 | 234 | return ; 235 | } 236 | } 237 | if (checkAlreadyRegTainted(reg_r)){ 238 | std::cout << std::hex << "[WRITE in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 239 | addMemTainted(addr); 240 | } 241 | } 242 | 243 | VOID spreadRegTaint(UINT64 insAddr, std::string insDis, UINT32 opCount, REG reg_r, REG reg_w) 244 | { 245 | if (opCount != 2) 246 | return; 247 | 248 | if (REG_valid(reg_w)){ 249 | if (checkAlreadyRegTainted(reg_w) && (!REG_valid(reg_r) || !checkAlreadyRegTainted(reg_r))){ 250 | std::cout << "[SPREAD]\t\t" << insAddr << ": " << insDis << std::endl; 251 | std::cout << "\t\t\toutput: "<< REG_StringShort(reg_w) << " | input: " << (REG_valid(reg_r) ? REG_StringShort(reg_r) : "constant") << std::endl; 252 | removeRegTainted(reg_w); 253 | } 254 | else if (!checkAlreadyRegTainted(reg_w) && checkAlreadyRegTainted(reg_r)){ 255 | std::cout << "[SPREAD]\t\t" << insAddr << ": " << insDis << std::endl; 256 | std::cout << "\t\t\toutput: " << REG_StringShort(reg_w) << " | input: "<< REG_StringShort(reg_r) << std::endl; 257 | taintReg(reg_w); 258 | } 259 | } 260 | } 261 | 262 | VOID followData(UINT64 insAddr, std::string insDis, REG reg) 263 | { 264 | if (!REG_valid(reg)) 265 | return; 266 | 267 | if (checkAlreadyRegTainted(reg)){ 268 | std::cout << "[FOLLOW]\t\t" << insAddr << ": " << insDis << std::endl; 269 | } 270 | } 271 | 272 | VOID Instruction(INS ins, VOID *v) 273 | { 274 | if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsRead(ins, 0) && INS_OperandIsReg(ins, 0)){ 275 | INS_InsertCall( 276 | ins, IPOINT_BEFORE, (AFUNPTR)ReadMem, 277 | IARG_ADDRINT, INS_Address(ins), 278 | IARG_PTR, new string(INS_Disassemble(ins)), 279 | IARG_UINT32, INS_OperandCount(ins), 280 | IARG_UINT32, INS_OperandReg(ins, 0), 281 | IARG_MEMORYOP_EA, 0, 282 | IARG_REG_VALUE, REG_STACK_PTR, 283 | IARG_END); 284 | } 285 | else if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsWritten(ins, 0)){ 286 | INS_InsertCall( 287 | ins, IPOINT_BEFORE, (AFUNPTR)WriteMem, 288 | IARG_ADDRINT, INS_Address(ins), 289 | IARG_PTR, new string(INS_Disassemble(ins)), 290 | IARG_UINT32, INS_OperandCount(ins), 291 | IARG_UINT32, INS_OperandReg(ins, 1), 292 | IARG_MEMORYOP_EA, 0, 293 | IARG_REG_VALUE, REG_STACK_PTR, 294 | IARG_END); 295 | } 296 | else if (INS_OperandCount(ins) > 1 && INS_OperandIsReg(ins, 0)){ 297 | INS_InsertCall( 298 | ins, IPOINT_BEFORE, (AFUNPTR)spreadRegTaint, 299 | IARG_ADDRINT, INS_Address(ins), 300 | IARG_PTR, new string(INS_Disassemble(ins)), 301 | IARG_UINT32, INS_OperandCount(ins), 302 | IARG_UINT32, INS_RegR(ins, 0), 303 | IARG_UINT32, INS_RegW(ins, 0), 304 | IARG_END); 305 | } 306 | 307 | if (INS_OperandCount(ins) > 1 && INS_OperandIsReg(ins, 0)){ 308 | INS_InsertCall( 309 | ins, IPOINT_BEFORE, (AFUNPTR)followData, 310 | IARG_ADDRINT, INS_Address(ins), 311 | IARG_PTR, new string(INS_Disassemble(ins)), 312 | IARG_UINT32, INS_RegR(ins, 0), 313 | IARG_END); 314 | } 315 | } 316 | 317 | VOID callbackBeforeMalloc(ADDRINT size) 318 | { 319 | lastSize = size; 320 | } 321 | 322 | VOID callbackBeforeFree(ADDRINT addr) 323 | { 324 | list::iterator i; 325 | 326 | std::cout << "[INFO]\t\tfree(" << std::hex << addr << ")" << std::endl; 327 | for(i = mallocAreaList.begin(); i != mallocAreaList.end(); i++){ 328 | if (addr == i->base){ 329 | i->status = FREE; 330 | break; 331 | } 332 | } 333 | } 334 | 335 | VOID callbackAfterMalloc(ADDRINT ret) 336 | { 337 | list::iterator i; 338 | struct mallocArea elem; 339 | 340 | std::cout << "[INFO]\t\tmalloc(" << lastSize << ") = " << std::hex << ret << std::endl; 341 | if (ret){ 342 | 343 | for(i = mallocAreaList.begin(); i != mallocAreaList.end(); i++){ 344 | if (ret == i->base){ 345 | i->status = ALLOCATE; 346 | i->size = lastSize; 347 | return; 348 | } 349 | } 350 | elem.base = ret; 351 | elem.size = lastSize; 352 | elem.status = ALLOCATE; 353 | mallocAreaList.push_front(elem); 354 | } 355 | } 356 | 357 | VOID Image(IMG img, VOID *v) 358 | { 359 | RTN mallocRtn = RTN_FindByName(img, "malloc"); 360 | RTN freeRtn = RTN_FindByName(img, "free"); 361 | 362 | if (RTN_Valid(mallocRtn)){ 363 | RTN_Open(mallocRtn); 364 | 365 | RTN_InsertCall( 366 | mallocRtn, 367 | IPOINT_BEFORE, (AFUNPTR)callbackBeforeMalloc, 368 | IARG_FUNCARG_ENTRYPOINT_VALUE, 0, 369 | IARG_END); 370 | 371 | RTN_InsertCall( 372 | mallocRtn, 373 | IPOINT_AFTER, (AFUNPTR)callbackAfterMalloc, 374 | IARG_FUNCRET_EXITPOINT_VALUE, 375 | IARG_END); 376 | 377 | RTN_Close(mallocRtn); 378 | } 379 | 380 | if (RTN_Valid(freeRtn)){ 381 | RTN_Open(freeRtn); 382 | RTN_InsertCall( 383 | freeRtn, 384 | IPOINT_BEFORE, (AFUNPTR)callbackBeforeFree, 385 | IARG_FUNCARG_ENTRYPOINT_VALUE, 0, 386 | IARG_END); 387 | RTN_Close(freeRtn); 388 | } 389 | } 390 | 391 | int main(int argc, char *argv[]) 392 | { 393 | PIN_InitSymbols(); 394 | if(PIN_Init(argc, argv)){ 395 | return Usage(); 396 | } 397 | 398 | PIN_SetSyntaxIntel(); 399 | IMG_AddInstrumentFunction(Image, 0); 400 | INS_AddInstrumentFunction(Instruction, 0); 401 | PIN_StartProgram(); 402 | 403 | return 0; 404 | } 405 | 406 | -------------------------------------------------------------------------------- /ClassicalUseAfterFreePatternMatching/Taint.cpp.old: -------------------------------------------------------------------------------- 1 | // 2 | // Jonathan Salwan - Copyright (C) 2013-08 3 | // 4 | // http://shell-storm.org 5 | // http://twitter.com/JonathanSalwan 6 | // 7 | // Note: Example 5 - http://shell-storm.org/blog/Taint-analysis-with-Pin/ 8 | // Detect the classical use after free vulnerability 9 | // 10 | 11 | #include "pin.H" 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define LOCKED 1 18 | #define UNLOCKED !LOCKED 19 | 20 | #define ALLOCATE 1 21 | #define FREE !ALLOCATE 22 | 23 | #define TRICKS(){if (tryksOpen++ == 0)return;} 24 | #define checkLockTaint(){if(lockTaint)return;} 25 | 26 | static size_t lastSize; 27 | static unsigned int tryksOpen; 28 | 29 | struct mallocArea 30 | { 31 | UINT64 base; 32 | UINT64 size; 33 | BOOL status; 34 | }; 35 | 36 | UINT32 lockTaint = LOCKED; 37 | 38 | std::list addressTainted; 39 | std::list regsTainted; 40 | std::list mallocAreaList; 41 | 42 | KNOB KnobTaintFunc(KNOB_MODE_WRITEONCE, "pintool", "taintFunction", "main", "Taint specific function"); 43 | 44 | INT32 Usage() 45 | { 46 | std::cerr << "Ex 5" << std::endl; 47 | std::cerr << std::endl << KNOB_BASE::StringKnobSummary() << std::endl; 48 | return -1; 49 | } 50 | 51 | BOOL checkAlreadyRegTainted(REG reg) 52 | { 53 | list::iterator i; 54 | 55 | for(i = regsTainted.begin(); i != regsTainted.end(); i++){ 56 | if (*i == reg){ 57 | return true; 58 | } 59 | } 60 | return false; 61 | } 62 | 63 | VOID removeMemTainted(UINT64 addr) 64 | { 65 | addressTainted.remove(addr); 66 | std::cout << std::hex << "\t\t\t" << addr << " is now freed" << std::endl; 67 | } 68 | 69 | VOID addMemTainted(UINT64 addr) 70 | { 71 | addressTainted.push_back(addr); 72 | std::cout << std::hex << "\t\t\t" << addr << " is now tainted" << std::endl; 73 | } 74 | 75 | BOOL taintReg(REG reg) 76 | { 77 | if (checkAlreadyRegTainted(reg) == true){ 78 | std::cout << "\t\t\t" << REG_StringShort(reg) << " is already tainted" << std::endl; 79 | return false; 80 | } 81 | 82 | switch(reg){ 83 | 84 | case REG_RAX: regsTainted.push_front(REG_RAX); 85 | case REG_EAX: regsTainted.push_front(REG_EAX); 86 | case REG_AX: regsTainted.push_front(REG_AX); 87 | case REG_AH: regsTainted.push_front(REG_AH); 88 | case REG_AL: regsTainted.push_front(REG_AL); 89 | break; 90 | 91 | case REG_RBX: regsTainted.push_front(REG_RBX); 92 | case REG_EBX: regsTainted.push_front(REG_EBX); 93 | case REG_BX: regsTainted.push_front(REG_BX); 94 | case REG_BH: regsTainted.push_front(REG_BH); 95 | case REG_BL: regsTainted.push_front(REG_BL); 96 | break; 97 | 98 | case REG_RCX: regsTainted.push_front(REG_RCX); 99 | case REG_ECX: regsTainted.push_front(REG_ECX); 100 | case REG_CX: regsTainted.push_front(REG_CX); 101 | case REG_CH: regsTainted.push_front(REG_CH); 102 | case REG_CL: regsTainted.push_front(REG_CL); 103 | break; 104 | 105 | case REG_RDX: regsTainted.push_front(REG_RDX); 106 | case REG_EDX: regsTainted.push_front(REG_EDX); 107 | case REG_DX: regsTainted.push_front(REG_DX); 108 | case REG_DH: regsTainted.push_front(REG_DH); 109 | case REG_DL: regsTainted.push_front(REG_DL); 110 | break; 111 | 112 | case REG_RDI: regsTainted.push_front(REG_RDI); 113 | case REG_EDI: regsTainted.push_front(REG_EDI); 114 | case REG_DI: regsTainted.push_front(REG_DI); 115 | case REG_DIL: regsTainted.push_front(REG_DIL); 116 | break; 117 | 118 | case REG_RSI: regsTainted.push_front(REG_RSI); 119 | case REG_ESI: regsTainted.push_front(REG_ESI); 120 | case REG_SI: regsTainted.push_front(REG_SI); 121 | case REG_SIL: regsTainted.push_front(REG_SIL); 122 | break; 123 | 124 | default: 125 | std::cout << "\t\t\t" << REG_StringShort(reg) << " can't be tainted" << std::endl; 126 | return false; 127 | } 128 | std::cout << "\t\t\t" << REG_StringShort(reg) << " is now tainted" << std::endl; 129 | return true; 130 | } 131 | 132 | BOOL removeRegTainted(REG reg) 133 | { 134 | switch(reg){ 135 | 136 | case REG_RAX: regsTainted.remove(REG_RAX); 137 | case REG_EAX: regsTainted.remove(REG_EAX); 138 | case REG_AX: regsTainted.remove(REG_AX); 139 | case REG_AH: regsTainted.remove(REG_AH); 140 | case REG_AL: regsTainted.remove(REG_AL); 141 | break; 142 | 143 | case REG_RBX: regsTainted.remove(REG_RBX); 144 | case REG_EBX: regsTainted.remove(REG_EBX); 145 | case REG_BX: regsTainted.remove(REG_BX); 146 | case REG_BH: regsTainted.remove(REG_BH); 147 | case REG_BL: regsTainted.remove(REG_BL); 148 | break; 149 | 150 | case REG_RCX: regsTainted.remove(REG_RCX); 151 | case REG_ECX: regsTainted.remove(REG_ECX); 152 | case REG_CX: regsTainted.remove(REG_CX); 153 | case REG_CH: regsTainted.remove(REG_CH); 154 | case REG_CL: regsTainted.remove(REG_CL); 155 | break; 156 | 157 | case REG_RDX: regsTainted.remove(REG_RDX); 158 | case REG_EDX: regsTainted.remove(REG_EDX); 159 | case REG_DX: regsTainted.remove(REG_DX); 160 | case REG_DH: regsTainted.remove(REG_DH); 161 | case REG_DL: regsTainted.remove(REG_DL); 162 | break; 163 | 164 | case REG_RDI: regsTainted.remove(REG_RDI); 165 | case REG_EDI: regsTainted.remove(REG_EDI); 166 | case REG_DI: regsTainted.remove(REG_DI); 167 | case REG_DIL: regsTainted.remove(REG_DIL); 168 | break; 169 | 170 | case REG_RSI: regsTainted.remove(REG_RSI); 171 | case REG_ESI: regsTainted.remove(REG_ESI); 172 | case REG_SI: regsTainted.remove(REG_SI); 173 | case REG_SIL: regsTainted.remove(REG_SIL); 174 | break; 175 | 176 | default: 177 | return false; 178 | } 179 | std::cout << "\t\t\t" << REG_StringShort(reg) << " is now freed" << std::endl; 180 | return true; 181 | } 182 | 183 | VOID ReadMem(INS ins, UINT64 memOp, ADDRINT sp) 184 | { 185 | list::iterator i; 186 | list::iterator i2; 187 | UINT64 addr = memOp; 188 | REG reg_r; 189 | 190 | checkLockTaint(); 191 | 192 | if (INS_OperandCount(ins) != 2) 193 | return; 194 | 195 | for(i2 = mallocAreaList.begin(); i2 != mallocAreaList.end(); i2++){ 196 | if (addr >= i2->base && addr < (i2->base + i2->size) && i2->status == FREE){ 197 | std::cout << std::hex << "[UAF in " << addr << "]\t" << INS_Address(ins) << ": " << INS_Disassemble(ins) << std::endl; 198 | return; 199 | } 200 | } 201 | 202 | reg_r = INS_OperandReg(ins, 0); 203 | for(i = addressTainted.begin(); i != addressTainted.end(); i++){ 204 | if (addr == *i){ 205 | std::cout << std::hex << "[READ in " << addr << "]\t" << INS_Address(ins) << ": " << INS_Disassemble(ins) << std::endl; 206 | taintReg(reg_r); 207 | 208 | if (sp > addr && addr > 0x700000000000) 209 | std::cout << std::hex << "[UAF in " << addr << "]\t" << INS_Address(ins) << ": " << INS_Disassemble(ins) << std::endl; 210 | 211 | return; 212 | } 213 | } 214 | /* if mem != tained and reg == taint => free the reg */ 215 | if (checkAlreadyRegTainted(reg_r)){ 216 | std::cout << std::hex << "[READ in " << addr << "]\t" << INS_Address(ins) << ": " << INS_Disassemble(ins) << std::endl; 217 | removeRegTainted(reg_r); 218 | } 219 | } 220 | 221 | VOID WriteMem(INS ins, UINT64 memOp, ADDRINT sp) 222 | { 223 | list::iterator i; 224 | list::iterator i2; 225 | UINT64 addr = memOp; 226 | REG reg_r; 227 | 228 | checkLockTaint(); 229 | 230 | if (INS_OperandCount(ins) != 2) 231 | return; 232 | 233 | for(i2 = mallocAreaList.begin(); i2 != mallocAreaList.end(); i2++){ 234 | if (addr >= i2->base && addr < (i2->base + i2->size) && i2->status == FREE){ 235 | std::cout << std::hex << "[UAF in " << addr << "]\t" << INS_Address(ins) << ": " << INS_Disassemble(ins) << std::endl; 236 | return; 237 | } 238 | } 239 | 240 | reg_r = INS_OperandReg(ins, 1); 241 | for(i = addressTainted.begin(); i != addressTainted.end(); i++){ 242 | if (addr == *i){ 243 | std::cout << std::hex << "[WRITE in " << addr << "]\t" << INS_Address(ins) << ": " << INS_Disassemble(ins) << std::endl; 244 | if (!REG_valid(reg_r) || !checkAlreadyRegTainted(reg_r)) 245 | removeMemTainted(addr); 246 | 247 | if (sp > addr && addr > 0x700000000000) 248 | std::cout << std::hex << "[UAF in " << addr << "]\t" << INS_Address(ins) << ": " << INS_Disassemble(ins) << std::endl; 249 | 250 | return ; 251 | } 252 | } 253 | if (checkAlreadyRegTainted(reg_r)){ 254 | std::cout << std::hex << "[WRITE in " << addr << "]\t" << INS_Address(ins) << ": " << INS_Disassemble(ins) << std::endl; 255 | addMemTainted(addr); 256 | } 257 | } 258 | 259 | VOID spreadRegTaint(INS ins) 260 | { 261 | REG reg_r, reg_w; 262 | 263 | checkLockTaint(); 264 | 265 | if (INS_OperandCount(ins) != 2) 266 | return; 267 | 268 | reg_r = INS_RegR(ins, 0); 269 | reg_w = INS_RegW(ins, 0); 270 | 271 | if (REG_valid(reg_w)){ 272 | if (checkAlreadyRegTainted(reg_w) && (!REG_valid(reg_r) || !checkAlreadyRegTainted(reg_r))){ 273 | std::cout << "[SPREAD]\t\t" << INS_Address(ins) << ": " << INS_Disassemble(ins) << std::endl; 274 | std::cout << "\t\t\toutput: "<< REG_StringShort(reg_w) << " | input: " << (REG_valid(reg_r) ? REG_StringShort(reg_r) : "constant") << std::endl; 275 | removeRegTainted(reg_w); 276 | } 277 | else if (!checkAlreadyRegTainted(reg_w) && checkAlreadyRegTainted(reg_r)){ 278 | std::cout << "[SPREAD]\t\t" << INS_Address(ins) << ": " << INS_Disassemble(ins) << std::endl; 279 | std::cout << "\t\t\toutput: " << REG_StringShort(reg_w) << " | input: "<< REG_StringShort(reg_r) << std::endl; 280 | taintReg(reg_w); 281 | } 282 | } 283 | } 284 | 285 | VOID followData(INS ins) 286 | { 287 | REG reg; 288 | 289 | checkLockTaint(); 290 | 291 | reg = INS_RegR(ins, 0); 292 | if (!REG_valid(reg)) 293 | return; 294 | 295 | if (checkAlreadyRegTainted(reg)){ 296 | std::cout << "[FOLLOW]\t\t" << INS_Address(ins) << ": " << INS_Disassemble(ins) << std::endl; 297 | } 298 | } 299 | 300 | VOID Instruction(INS ins, VOID *v) 301 | { 302 | if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsRead(ins, 0) && INS_OperandIsReg(ins, 0)){ 303 | INS_InsertCall( 304 | ins, IPOINT_BEFORE, (AFUNPTR)ReadMem, 305 | IARG_PTR, ins, 306 | IARG_MEMORYOP_EA, 0, 307 | IARG_REG_VALUE, REG_STACK_PTR, 308 | IARG_END); 309 | } 310 | else if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsWritten(ins, 0)){ 311 | INS_InsertCall( 312 | ins, IPOINT_BEFORE, (AFUNPTR)WriteMem, 313 | IARG_PTR, ins, 314 | IARG_MEMORYOP_EA, 0, 315 | IARG_REG_VALUE, REG_STACK_PTR, 316 | IARG_END); 317 | } 318 | else if (INS_OperandCount(ins) > 1 && INS_OperandIsReg(ins, 0)){ 319 | INS_InsertCall( 320 | ins, IPOINT_BEFORE, (AFUNPTR)spreadRegTaint, 321 | IARG_PTR, ins, 322 | IARG_END); 323 | } 324 | 325 | if (INS_OperandCount(ins) > 1 && INS_OperandIsReg(ins, 0)){ 326 | INS_InsertCall( 327 | ins, IPOINT_BEFORE, (AFUNPTR)followData, 328 | IARG_PTR, ins, 329 | IARG_END); 330 | } 331 | } 332 | 333 | VOID Syscall_entry(THREADID thread_id, CONTEXT *ctx, SYSCALL_STANDARD std, void *v) 334 | { 335 | unsigned int i; 336 | UINT64 start, size; 337 | 338 | if (PIN_GetSyscallNumber(ctx, std) == __NR_read){ 339 | 340 | TRICKS(); /* tricks to ignore the first open */ 341 | 342 | start = static_cast((PIN_GetSyscallArgument(ctx, std, 1))); 343 | size = static_cast((PIN_GetSyscallArgument(ctx, std, 2))); 344 | 345 | for (i = 0; i < size; i++) 346 | addressTainted.push_back(start+i); 347 | 348 | std::cout << "[TAINT]\t\t\tbytes tainted from " << std::hex << "0x" << start << " to 0x" << start+size << " (via read)"<< std::endl; 349 | } 350 | } 351 | 352 | VOID callbackBeforeMalloc(ADDRINT size) 353 | { 354 | checkLockTaint(); 355 | lastSize = size; 356 | } 357 | 358 | VOID callbackBeforeFree(ADDRINT addr) 359 | { 360 | list::iterator i; 361 | 362 | checkLockTaint(); 363 | 364 | std::cout << "[INFO]\t\tfree(" << std::hex << addr << ")" << std::endl; 365 | for(i = mallocAreaList.begin(); i != mallocAreaList.end(); i++){ 366 | if (addr == i->base){ 367 | i->status = FREE; 368 | break; 369 | } 370 | } 371 | } 372 | 373 | VOID callbackAfterMalloc(ADDRINT ret) 374 | { 375 | list::iterator i; 376 | struct mallocArea elem; 377 | 378 | checkLockTaint(); 379 | 380 | std::cout << "[INFO]\t\tmalloc(" << lastSize << ") = " << std::hex << ret << std::endl; 381 | if (ret){ 382 | 383 | for(i = mallocAreaList.begin(); i != mallocAreaList.end(); i++){ 384 | if (ret == i->base){ 385 | i->status = ALLOCATE; 386 | i->size = lastSize; 387 | return; 388 | } 389 | } 390 | elem.base = ret; 391 | elem.size = lastSize; 392 | elem.status = ALLOCATE; 393 | mallocAreaList.push_front(elem); 394 | } 395 | } 396 | 397 | VOID startTaint(CHAR *name) 398 | { 399 | lockTaint = UNLOCKED; 400 | std::cout << "[INFO]\t\tThe " << name << " function is called. The taint analysis begins." << std::endl; 401 | } 402 | 403 | VOID stopTaint(CHAR *name) 404 | { 405 | lockTaint = LOCKED; 406 | std::cout << "[INFO]\t\tThe " << name << " function is over. The taint analysis stop." << std::endl; 407 | } 408 | 409 | 410 | VOID Image(IMG img, VOID *v) 411 | { 412 | const char *optFunc = KnobTaintFunc.Value().c_str(); 413 | RTN RtnFunc = RTN_FindByName(img, optFunc); 414 | RTN mallocRtn = RTN_FindByName(img, "malloc"); 415 | RTN freeRtn = RTN_FindByName(img, "free"); 416 | 417 | if (RTN_Valid(mallocRtn)){ 418 | RTN_Open(mallocRtn); 419 | 420 | RTN_InsertCall( 421 | mallocRtn, 422 | IPOINT_BEFORE, (AFUNPTR)callbackBeforeMalloc, 423 | IARG_FUNCARG_ENTRYPOINT_VALUE, 0, 424 | IARG_END); 425 | 426 | RTN_InsertCall( 427 | mallocRtn, 428 | IPOINT_AFTER, (AFUNPTR)callbackAfterMalloc, 429 | IARG_FUNCRET_EXITPOINT_VALUE, 430 | IARG_END); 431 | 432 | RTN_Close(mallocRtn); 433 | } 434 | 435 | if (RTN_Valid(freeRtn)){ 436 | RTN_Open(freeRtn); 437 | RTN_InsertCall( 438 | freeRtn, 439 | IPOINT_BEFORE, (AFUNPTR)callbackBeforeFree, 440 | IARG_FUNCARG_ENTRYPOINT_VALUE, 0, 441 | IARG_END); 442 | RTN_Close(freeRtn); 443 | } 444 | 445 | if (RTN_Valid(RtnFunc)){ 446 | RTN_Open(RtnFunc); 447 | 448 | RTN_InsertCall( 449 | RtnFunc, 450 | IPOINT_BEFORE, (AFUNPTR)startTaint, 451 | IARG_ADDRINT, optFunc, 452 | IARG_END); 453 | 454 | RTN_InsertCall( 455 | RtnFunc, 456 | IPOINT_AFTER, (AFUNPTR)stopTaint, 457 | IARG_ADDRINT, optFunc, 458 | IARG_END); 459 | 460 | RTN_Close(RtnFunc); 461 | } 462 | 463 | } 464 | 465 | int main(int argc, char *argv[]) 466 | { 467 | PIN_InitSymbols(); 468 | if(PIN_Init(argc, argv)){ 469 | return Usage(); 470 | } 471 | 472 | PIN_SetSyntaxIntel(); 473 | IMG_AddInstrumentFunction(Image, 0); 474 | //PIN_AddSyscallEntryFunction(Syscall_entry, 0); 475 | INS_AddInstrumentFunction(Instruction, 0); 476 | PIN_StartProgram(); 477 | 478 | return 0; 479 | } 480 | 481 | -------------------------------------------------------------------------------- /ClassicalUseAfterFreePatternMatching/crackme: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/ClassicalUseAfterFreePatternMatching/crackme -------------------------------------------------------------------------------- /ClassicalUseAfterFreePatternMatching/crackme.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Jonathan Salwan - Copyright (C) 2013-07 3 | ** 4 | ** http://twitter.com/JonathanSalwan 5 | ** http://shell-storm.org 6 | ** 7 | ** This program is free software: you can redistribute it and/or modify 8 | ** it under the terms of the GNU General Public License as published by 9 | ** the Free Software Foundation, either version 3 of the License, or 10 | ** (at your option) any later version. 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | char *serial = "\x30\x39\x3c\x21\x30"; 19 | 20 | int main(void) 21 | { 22 | int fd, i = 0; 23 | char *buf; 24 | char *r; 25 | 26 | buf = malloc(256); 27 | if (!buf) 28 | return -1; 29 | r = buf; 30 | fd = open("serial.txt", O_RDONLY); 31 | read(fd, buf, 256); 32 | close(fd); 33 | while (i < 5){ 34 | if ((*buf ^ 0x55) != *serial) 35 | return 0; 36 | buf++, serial++, i++; 37 | } 38 | if (!*buf) 39 | printf("Good boy\n"); 40 | free(r); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /ClassicalUseAfterFreePatternMatching/file.txt: -------------------------------------------------------------------------------- 1 | ABCD 2 | -------------------------------------------------------------------------------- /ClassicalUseAfterFreePatternMatching/makefile: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # DO NOT EDIT THIS FILE! 4 | # 5 | ############################################################## 6 | 7 | # If the tool is built out of the kit, PIN_ROOT must be specified in the make invocation and point to the kit root. 8 | ifdef PIN_ROOT 9 | CONFIG_ROOT := $(PIN_ROOT)/source/tools/Config 10 | else 11 | CONFIG_ROOT := ../Config 12 | endif 13 | include $(CONFIG_ROOT)/makefile.config 14 | include makefile.rules 15 | include $(TOOLS_ROOT)/Config/makefile.default.rules 16 | 17 | ############################################################## 18 | # 19 | # DO NOT EDIT THIS FILE! 20 | # 21 | ############################################################## 22 | -------------------------------------------------------------------------------- /ClassicalUseAfterFreePatternMatching/makefile.rules: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # This file includes all the test targets as well as all the 4 | # non-default build rules and test recipes. 5 | # 6 | ############################################################## 7 | 8 | 9 | ############################################################## 10 | # 11 | # Test targets 12 | # 13 | ############################################################## 14 | 15 | ###### Place all generic definitions here ###### 16 | 17 | # This defines tests which run tools of the same name. This is simply for convenience to avoid 18 | # defining the test name twice (once in TOOL_ROOTS and again in TEST_ROOTS). 19 | # Tests defined here should not be defined in TOOL_ROOTS and TEST_ROOTS. 20 | TEST_TOOL_ROOTS := Taint 21 | 22 | # This defines the tests to be run that were not already defined in TEST_TOOL_ROOTS. 23 | TEST_ROOTS := 24 | 25 | # This defines a list of tests that should run in the "short" sanity. Tests in this list must also 26 | # appear either in the TEST_TOOL_ROOTS or the TEST_ROOTS list. 27 | # If the entire directory should be tested in sanity, assign TEST_TOOL_ROOTS and TEST_ROOTS to the 28 | # SANITY_SUBSET variable in the tests section below (see example in makefile.rules.tmpl). 29 | SANITY_SUBSET := 30 | 31 | # This defines the tools which will be run during the the tests, and were not already defined in 32 | # TEST_TOOL_ROOTS. 33 | TOOL_ROOTS := 34 | 35 | # This defines the static analysis tools which will be run during the the tests. They should not 36 | # be defined in TEST_TOOL_ROOTS. If a test with the same name exists, it should be defined in 37 | # TEST_ROOTS. 38 | # Note: Static analysis tools are in fact executables linked with the Pin Static Analysis Library. 39 | # This library provides a subset of the Pin APIs which allows the tool to perform static analysis 40 | # of an application or dll. Pin itself is not used when this tool runs. 41 | SA_TOOL_ROOTS := 42 | 43 | # This defines all the applications that will be run during the tests. 44 | APP_ROOTS := 45 | 46 | # This defines any additional object files that need to be compiled. 47 | OBJECT_ROOTS := 48 | 49 | # This defines any additional dlls (shared objects), other than the pintools, that need to be compiled. 50 | DLL_ROOTS := 51 | 52 | # This defines any static libraries (archives), that need to be built. 53 | LIB_ROOTS := 54 | 55 | 56 | ############################################################## 57 | # 58 | # Test recipes 59 | # 60 | ############################################################## 61 | 62 | # This section contains recipes for tests other than the default. 63 | # See makefile.default.rules for the default test rules. 64 | # All tests in this section should adhere to the naming convention: .test 65 | 66 | 67 | ############################################################## 68 | # 69 | # Build rules 70 | # 71 | ############################################################## 72 | 73 | # This section contains the build rules for all binaries that have special build rules. 74 | # See makefile.default.rules for the default build rules. 75 | -------------------------------------------------------------------------------- /ClassicalUseAfterFreePatternMatching/pin.log: -------------------------------------------------------------------------------- 1 | Pin 2.12 kit 58423 2 | E: Missing application name 3 | -------------------------------------------------------------------------------- /ClassicalUseAfterFreePatternMatching/pintool.log: -------------------------------------------------------------------------------- 1 | Pin 2.12 kit 58423 2 | A: Source/pin/pin/image.cpp:RTN_Open:RTN_Open:3417: Must use RTN_Close on previous rtn before opening a new rtn 3 | 4 | -------------------------------------------------------------------------------- /ClassicalUseAfterFreePatternMatching/test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/ClassicalUseAfterFreePatternMatching/test -------------------------------------------------------------------------------- /ClassicalUseAfterFreePatternMatching/test.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define true 0 9 | #define false !true 10 | 11 | int main(int ac, char **av) 12 | { 13 | int fd; 14 | char *buf; 15 | char c; 16 | 17 | if (!(buf = malloc(32))) 18 | return -1; 19 | 20 | c = buf[0]; 21 | free(buf); 22 | c = buf[0]; 23 | buf = malloc(32); 24 | c = buf[0]; 25 | } 26 | -------------------------------------------------------------------------------- /ClassicalUseAfterFreePatternMatching/testcpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/ClassicalUseAfterFreePatternMatching/testcpp -------------------------------------------------------------------------------- /ClassicalUseAfterFreePatternMatching/testcpp.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Jonathan Salwan - Copyright (C) 2013-08 3 | // 4 | // http://shell-storm.org 5 | // http://twitter.com/JonathanSalwan 6 | // 7 | // This program is free software: you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation, either version 3 of the License, or 10 | // (at your option) any later version. 11 | // 12 | 13 | #include 14 | 15 | class Test 16 | { 17 | private: 18 | int a; 19 | void foo(void); 20 | 21 | public: 22 | Test(int num) { this->a = num; }; 23 | ~Test() {}; 24 | void wrapper(void); 25 | }; 26 | 27 | void Test::foo(void) 28 | { 29 | std::cout << this->a << std::endl; 30 | } 31 | 32 | void Test::wrapper(void) 33 | { 34 | this->foo(); 35 | } 36 | 37 | int main() 38 | { 39 | Test *ptr = new Test(1234); 40 | Test *old = ptr; 41 | 42 | ptr->wrapper(); 43 | delete ptr; 44 | ptr->wrapper(); 45 | ptr = new Test(4321); 46 | old->wrapper(); 47 | } 48 | -------------------------------------------------------------------------------- /ConcolicExecution/compile.sh: -------------------------------------------------------------------------------- 1 | g++ -DBIGARRAY_MULTIPLIER=1 -DUSING_XED -Wall -Werror -Wno-unknown-pragmas -fno-stack-protector -DTARGET_IA32E -DHOST_IA32E -fPIC -DTARGET_LINUX -I../../../source/include/pin -I../../../source/include/pin/gen -I../../../extras/components/include -I./z3/src/api/c++ -I../../../extras/xed2-intel64/include -I../../../source/tools/InstLib -O3 -fomit-frame-pointer -fno-strict-aliasing -c -o obj-intel64/ConcolicExecution.o ConcolicExecution.cpp 2 | 3 | g++ -shared -Wl,--hash-style=sysv -Wl,-Bsymbolic -Wl,--version-script=../../../source/include/pin/pintool.ver -o obj-intel64/ConcolicExecution.so obj-intel64/ConcolicExecution.o -L../../../intel64/lib -L../../../intel64/lib-ext -L../../../intel64/runtime/glibc -L../../../extras/xed2-intel64/lib -lpin -lxed -ldwarf -lelf -ldl -lz3 4 | -------------------------------------------------------------------------------- /ConcolicExecution/crackme1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/ConcolicExecution/crackme1 -------------------------------------------------------------------------------- /ConcolicExecution/crackme1.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Jonathan Salwan - 2013-08-22 3 | ** 4 | ** http://shell-storm.org 5 | ** http://twitter.com/JonathanSalwan 6 | ** 7 | ** This program is free software: you can redistribute it and/or modify 8 | ** it under the terms of the GNU General Public License as published by 9 | ** the Free Software Foundation, either version 3 of the License, or 10 | ** (at your option) any later version. 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | char *serial = "\x30\x39\x3c\x21\x30"; 19 | 20 | int main(void) 21 | { 22 | int fd, i = 0; 23 | char buf[260] = {0}; 24 | char *r = buf; 25 | 26 | fd = open("serial.txt", O_RDONLY); 27 | read(fd, r, 256); 28 | close(fd); 29 | while (i < 5){ 30 | if ((*r ^ (0x55)) != *serial) 31 | return 0; 32 | r++, serial++, i++; 33 | } 34 | if (!*r) 35 | printf("Good boy\n"); 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /ConcolicExecution/crackme2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/ConcolicExecution/crackme2 -------------------------------------------------------------------------------- /ConcolicExecution/crackme2.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Jonathan Salwan - 2013-08-22 3 | ** 4 | ** http://shell-storm.org 5 | ** http://twitter.com/JonathanSalwan 6 | ** 7 | ** This program is free software: you can redistribute it and/or modify 8 | ** it under the terms of the GNU General Public License as published by 9 | ** the Free Software Foundation, either version 3 of the License, or 10 | ** (at your option) any later version. 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | int main(void) 19 | { 20 | int fd; 21 | char buff[260] = {0}; 22 | 23 | fd = open("serial.txt", O_RDONLY); 24 | read(fd, buff, 256); 25 | close(fd); 26 | 27 | if (buff[0] != 'a') 28 | return 1; 29 | 30 | if (buff[1] != 'b') 31 | return 1; 32 | 33 | if (buff[2] != 'c') 34 | return 1; 35 | 36 | printf("Good boy\n"); 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /ConcolicExecution/crackme3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/ConcolicExecution/crackme3 -------------------------------------------------------------------------------- /ConcolicExecution/crackme3.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Jonathan Salwan - 2013-08-22 3 | ** 4 | ** http://shell-storm.org 5 | ** http://twitter.com/JonathanSalwan 6 | ** 7 | ** This program is free software: you can redistribute it and/or modify 8 | ** it under the terms of the GNU General Public License as published by 9 | ** the Free Software Foundation, either version 3 of the License, or 10 | ** (at your option) any later version. 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | char *serial = "\x30\x39\x3c\x21\x30"; 19 | 20 | int main(void) 21 | { 22 | int fd, i = 0; 23 | char buf[260] = {0}; 24 | char *r = buf; 25 | 26 | fd = open("serial.txt", O_RDONLY); 27 | read(fd, r, 256); 28 | close(fd); 29 | 30 | if ((buf[0] ^ 0x55) + 1 == 'A') 31 | printf("Good boy\n"); 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /ConcolicExecution/ex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/ConcolicExecution/ex -------------------------------------------------------------------------------- /ConcolicExecution/ex.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Jonathan Salwan - 2013-08-24 3 | // 4 | // http://shell-storm.org 5 | // http://twitter.com/JonathanSalwan 6 | // 7 | // This program is free software: you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation, either version 3 of the License, or 10 | // (at your option) any later version. 11 | // 12 | 13 | #include 14 | #include "z3++.h" 15 | 16 | //class SolveEq 17 | //{ 18 | // private: 19 | // z3::context *c; 20 | // z3::solver *s; 21 | // z3::expr *eq; 22 | // z3::model *m; 23 | // z3::expr *x; 24 | // 25 | // public: 26 | // SolveEq(); 27 | // ~SolveEq(); 28 | //}; 29 | // 30 | //SolveEq::SolveEq() 31 | //{ 32 | // this->c = new z3::context; 33 | // this->x = new z3::expr(c->bv_const("x", 32)); 34 | // this->s = new z3::solver(*(this->c)); 35 | // this->eq = new z3::expr(*(this->x)); 36 | //}; 37 | // 38 | //SolveEq::~SolveEq() 39 | //{ 40 | // delete this->c; 41 | // delete this->x; 42 | // delete this->s; 43 | // delete this->eq; 44 | //} 45 | // 46 | //SolveEq::setExpr(z3::expr &expr) 47 | //{ 48 | // *(this->eq) = expr; 49 | //} 50 | 51 | int main(int ac, const char *av[]) 52 | { 53 | z3::context *c; 54 | z3::expr *x; 55 | z3::solver *s; 56 | z3::expr *eq; 57 | z3::model *m; 58 | 59 | c = new z3::context; 60 | x = new z3::expr(c->bv_const("x", 32)); 61 | s = new z3::solver(*c); 62 | eq = new z3::expr(*x); 63 | 64 | *eq = (*x ^ 0x55); 65 | *eq = (*eq == 0x30); 66 | 67 | s->add(*eq); 68 | 69 | std::cout << s->check() << "\n"; 70 | m = new z3::model(s->get_model()); 71 | std::cout << *m << "\n"; 72 | 73 | delete m; 74 | delete eq; 75 | delete x; 76 | delete s; 77 | delete c; 78 | 79 | // ---------------------------- 80 | 81 | c = new z3::context; 82 | x = new z3::expr(c->bv_const("x", 32)); 83 | s = new z3::solver(*c); 84 | eq = new z3::expr(*x); 85 | 86 | *eq = (*x ^ 0x55); 87 | *eq = (*eq == 0x39); 88 | 89 | s->add(*eq); 90 | 91 | std::cout << s->check() << "\n"; 92 | m = new z3::model(s->get_model()); 93 | std::cout << *m << "\n"; 94 | 95 | delete m; 96 | delete eq; 97 | delete x; 98 | delete s; 99 | delete c; 100 | 101 | return 0; 102 | } 103 | 104 | -------------------------------------------------------------------------------- /ConcolicExecution/makefile: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # DO NOT EDIT THIS FILE! 4 | # 5 | ############################################################## 6 | 7 | # If the tool is built out of the kit, PIN_ROOT must be specified in the make invocation and point to the kit root. 8 | ifdef PIN_ROOT 9 | CONFIG_ROOT := $(PIN_ROOT)/source/tools/Config 10 | else 11 | CONFIG_ROOT := ../Config 12 | endif 13 | include $(CONFIG_ROOT)/makefile.config 14 | include makefile.rules 15 | include $(TOOLS_ROOT)/Config/makefile.default.rules 16 | 17 | TOOL_INCLUDES += ./src/api/c++/ 18 | 19 | ############################################################## 20 | # 21 | # DO NOT EDIT THIS FILE! 22 | # 23 | ############################################################## 24 | -------------------------------------------------------------------------------- /ConcolicExecution/makefile.rules: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # This file includes all the test targets as well as all the 4 | # non-default build rules and test recipes. 5 | # 6 | ############################################################## 7 | 8 | 9 | ############################################################## 10 | # 11 | # Test targets 12 | # 13 | ############################################################## 14 | 15 | ###### Place all generic definitions here ###### 16 | 17 | # This defines tests which run tools of the same name. This is simply for convenience to avoid 18 | # defining the test name twice (once in TOOL_ROOTS and again in TEST_ROOTS). 19 | # Tests defined here should not be defined in TOOL_ROOTS and TEST_ROOTS. 20 | TEST_TOOL_ROOTS := ConcolicExecution 21 | 22 | # This defines the tests to be run that were not already defined in TEST_TOOL_ROOTS. 23 | TEST_ROOTS := 24 | 25 | # This defines a list of tests that should run in the "short" sanity. Tests in this list must also 26 | # appear either in the TEST_TOOL_ROOTS or the TEST_ROOTS list. 27 | # If the entire directory should be tested in sanity, assign TEST_TOOL_ROOTS and TEST_ROOTS to the 28 | # SANITY_SUBSET variable in the tests section below (see example in makefile.rules.tmpl). 29 | SANITY_SUBSET := 30 | 31 | # This defines the tools which will be run during the the tests, and were not already defined in 32 | # TEST_TOOL_ROOTS. 33 | TOOL_ROOTS := 34 | 35 | # This defines the static analysis tools which will be run during the the tests. They should not 36 | # be defined in TEST_TOOL_ROOTS. If a test with the same name exists, it should be defined in 37 | # TEST_ROOTS. 38 | # Note: Static analysis tools are in fact executables linked with the Pin Static Analysis Library. 39 | # This library provides a subset of the Pin APIs which allows the tool to perform static analysis 40 | # of an application or dll. Pin itself is not used when this tool runs. 41 | SA_TOOL_ROOTS := 42 | 43 | # This defines all the applications that will be run during the tests. 44 | APP_ROOTS := 45 | 46 | # This defines any additional object files that need to be compiled. 47 | OBJECT_ROOTS := 48 | 49 | # This defines any additional dlls (shared objects), other than the pintools, that need to be compiled. 50 | DLL_ROOTS := 51 | 52 | # This defines any static libraries (archives), that need to be built. 53 | LIB_ROOTS := z3/build/libz3.so 54 | 55 | 56 | ############################################################## 57 | # 58 | # Test recipes 59 | # 60 | ############################################################## 61 | 62 | # This section contains recipes for tests other than the default. 63 | # See makefile.default.rules for the default test rules. 64 | # All tests in this section should adhere to the naming convention: .test 65 | 66 | 67 | ############################################################## 68 | # 69 | # Build rules 70 | # 71 | ############################################################## 72 | 73 | # This section contains the build rules for all binaries that have special build rules. 74 | # See makefile.default.rules for the default build rules. 75 | -------------------------------------------------------------------------------- /ConcolicExecution/none: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/ConcolicExecution/none -------------------------------------------------------------------------------- /ConcolicExecution/pin.log: -------------------------------------------------------------------------------- 1 | Pin 2.12 kit 58423 2 | E: Missing application name 3 | -------------------------------------------------------------------------------- /ConcolicExecution/pintool.log: -------------------------------------------------------------------------------- 1 | Pin 2.12 kit 58423 2 | A: Source/pin/core_ia32/operand_ia32.cpp:INS_OperandImmediate:INS_OperandImmediate:409: assertion failed: opname == XED_OPERAND_IMM0 ||opname ==XED_OPERAND_IMM1 3 | 4 | -------------------------------------------------------------------------------- /ConcolicExecution/serial.txt: -------------------------------------------------------------------------------- 1 | e -------------------------------------------------------------------------------- /FormatStringDetection/file.txt: -------------------------------------------------------------------------------- 1 | ABCD -------------------------------------------------------------------------------- /FormatStringDetection/frmtstr.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Jonathan Salwan - Copyright (C) 2014-11-11 3 | // 4 | // http://shell-storm.org 5 | // http://twitter.com/JonathanSalwan 6 | // 7 | // Note: PoC - Detect a format string vulnerability without pattern matching. 8 | // 9 | // In this PoC, we can see that it's possible to detect some format string bugs without 10 | // pattern matching (e.g: looking for %s or something like that). We only focus on the 11 | // taint analysis and look if the va_arg based functions' first argument is tainted or 12 | // not. 13 | // 14 | // Let's take an example by monitoring printf. On x86_64, we know that the RDI register 15 | // holds the first argument. So, if RDI points to a tainted memory area, it's probably 16 | // means that we can trigger a bug, otherwise it's safe. 17 | // 18 | // In this PoC, I only taint bytes comming from files by monitoring the syscall sys_open. 19 | // Feel free to add other syscalls and/or environements (argv...). 20 | // 21 | // Let's use this following vulnerable code as an example: 22 | // 23 | // | void foo(char *buf) 24 | // | { 25 | // | unsigned int i; 26 | // | char *ptr; 27 | // | 28 | // | if (!(ptr = malloc(8))) 29 | // | return; 30 | // | 31 | // | for (i = 0; i < 8; i++) 32 | // | ptr[i] = buf[i]; /* spread the taint to another area */ 33 | // | 34 | // | printf(ptr); /* warn format string */ 35 | // | } 36 | // | 37 | // | int main(int ac, char **av) 38 | // | { 39 | // | int fd; 40 | // | char *buf; 41 | // | 42 | // | if (!(buf = malloc(8))) 43 | // | return -1; 44 | // | 45 | // | fd = open("./file.txt", O_RDONLY); 46 | // | read(fd, buf, 8); /* The range [buff, buff+8] is tainted */ 47 | // | close(fd); 48 | // | 49 | // | foo(buf); 50 | // | } 51 | // 52 | // And now, let's run the Pin tool: 53 | // 54 | // | $ ../../../pin -t ./obj-intel64/frmtstr.so -- ./test 55 | // | [TAINT] bytes tainted from 0x874010 to 0x874018 (via read) 56 | // | [READ in 874010] 4006cd: movzx eax, byte ptr [rax] 57 | // | eax is now tainted 58 | // | [WRITE in 874030] 4006d0: mov byte ptr [rdx], al 59 | // | 874030 is now tainted 60 | // | [READ in 874011] 4006cd: movzx eax, byte ptr [rax] 61 | // | eax is already tainted 62 | // | [WRITE in 874031] 4006d0: mov byte ptr [rdx], al 63 | // | 874031 is now tainted 64 | // | [READ in 874012] 4006cd: movzx eax, byte ptr [rax] 65 | // | eax is already tainted 66 | // | [WRITE in 874032] 4006d0: mov byte ptr [rdx], al 67 | // | 874032 is now tainted 68 | // | [READ in 874013] 4006cd: movzx eax, byte ptr [rax] 69 | // | eax is already tainted 70 | // | [WRITE in 874033] 4006d0: mov byte ptr [rdx], al 71 | // | 874033 is now tainted 72 | // | [READ in 874014] 4006cd: movzx eax, byte ptr [rax] 73 | // | eax is already tainted 74 | // | [WRITE in 874034] 4006d0: mov byte ptr [rdx], al 75 | // | 874034 is now tainted 76 | // | [READ in 874015] 4006cd: movzx eax, byte ptr [rax] 77 | // | eax is already tainted 78 | // | [WRITE in 874035] 4006d0: mov byte ptr [rdx], al 79 | // | 874035 is now tainted 80 | // | [READ in 874016] 4006cd: movzx eax, byte ptr [rax] 81 | // | eax is already tainted 82 | // | [WRITE in 874036] 4006d0: mov byte ptr [rdx], al 83 | // | 874036 is now tainted 84 | // | [READ in 874017] 4006cd: movzx eax, byte ptr [rax] 85 | // | eax is already tainted 86 | // | [WRITE in 874037] 4006d0: mov byte ptr [rdx], al 87 | // | 874037 is now tainted 88 | // | [SPREAD] 4006e3: mov eax, 0x0 89 | // | output: eax | input: constant 90 | // | eax is now freed 91 | // | [frmtstr] printf() is called 92 | // | [frmtstr] RDI content: ABCD 93 | // | [frmtstr] The RDI memory area is tagged as tainted 94 | // | [frmtstr] This printf is probably vulnerable 95 | // | [READ in 874030] 7f764d19fd43: movdqu xmm0, xmmword ptr [rdi] 96 | // | xmm0 can't be tainted 97 | // | [READ in 874030] 7f764d18935c: movzx esi, byte ptr [rbx] 98 | // | esi is now tainted 99 | // | [SPREAD] 7f764d1885b5: mov ebp, esi 100 | // | output: ebp | input: esi 101 | // | ebp can't be tainted 102 | // | [FOLLOW] 7f764d1885b5: mov ebp, esi 103 | // | [READ in 874031] 7f764d18935c: movzx esi, byte ptr [rbx] 104 | // | esi is already tainted 105 | // | [SPREAD] 7f764d1885b5: mov ebp, esi 106 | // | output: ebp | input: esi 107 | // | ebp can't be tainted 108 | // | [FOLLOW] 7f764d1885b5: mov ebp, esi 109 | // | [READ in 874032] 7f764d18935c: movzx esi, byte ptr [rbx] 110 | // | esi is already tainted 111 | // | [SPREAD] 7f764d1885b5: mov ebp, esi 112 | // | output: ebp | input: esi 113 | // | ebp can't be tainted 114 | // | [FOLLOW] 7f764d1885b5: mov ebp, esi 115 | // | [READ in 874033] 7f764d18935c: movzx esi, byte ptr [rbx] 116 | // | esi is already tainted 117 | // | [SPREAD] 7f764d1885b5: mov ebp, esi 118 | // | output: ebp | input: esi 119 | // | ebp can't be tainted 120 | // | [FOLLOW] 7f764d1885b5: mov ebp, esi 121 | // | [SPREAD] 7f764d148318: mov esi, ebx 122 | // | output: esi | input: ebx 123 | // | esi is now freed 124 | // 125 | // 126 | // As you can see, the Pin tool spreads the taint and raises a warning when printf is called 127 | // In this case, it's easier to define the vulnerability model like that than to check if the 128 | // first argument contains a secure string format (%s, %32s, %x, ...). 129 | // 130 | // This scenario is not limited to printf, we can also define a set of functions that uses 131 | // va_args and might be vulnerable as well. 132 | // 133 | 134 | 135 | #include "pin.H" 136 | #include 137 | #include 138 | #include 139 | #include 140 | 141 | #define LOCKED 1 142 | #define UNLOCKED !LOCKED 143 | 144 | #define ALLOCATE 1 145 | #define FREE !ALLOCATE 146 | 147 | 148 | 149 | struct mallocArea 150 | { 151 | UINT64 base; 152 | UINT64 size; 153 | BOOL status; 154 | }; 155 | 156 | UINT32 lockTaint = LOCKED; 157 | 158 | std::list addressTainted; 159 | std::list regsTainted; 160 | std::list mallocAreaList; 161 | 162 | INT32 Usage() 163 | { 164 | std::cerr << "PoC - frmtstr" << std::endl; 165 | return -1; 166 | } 167 | 168 | BOOL checkAlreadyRegTainted(REG reg) 169 | { 170 | list::iterator i; 171 | 172 | for(i = regsTainted.begin(); i != regsTainted.end(); i++){ 173 | if (*i == reg){ 174 | return true; 175 | } 176 | } 177 | return false; 178 | } 179 | 180 | VOID removeMemTainted(UINT64 addr) 181 | { 182 | addressTainted.remove(addr); 183 | std::cout << std::hex << "\t\t\t" << addr << " is now freed" << std::endl; 184 | } 185 | 186 | VOID addMemTainted(UINT64 addr) 187 | { 188 | addressTainted.push_back(addr); 189 | std::cout << std::hex << "\t\t\t" << addr << " is now tainted" << std::endl; 190 | } 191 | 192 | BOOL taintReg(REG reg) 193 | { 194 | if (checkAlreadyRegTainted(reg) == true){ 195 | std::cout << "\t\t\t" << REG_StringShort(reg) << " is already tainted" << std::endl; 196 | return false; 197 | } 198 | 199 | switch(reg){ 200 | 201 | case REG_RAX: regsTainted.push_front(REG_RAX); 202 | case REG_EAX: regsTainted.push_front(REG_EAX); 203 | case REG_AX: regsTainted.push_front(REG_AX); 204 | case REG_AH: regsTainted.push_front(REG_AH); 205 | case REG_AL: regsTainted.push_front(REG_AL); 206 | break; 207 | 208 | case REG_RBX: regsTainted.push_front(REG_RBX); 209 | case REG_EBX: regsTainted.push_front(REG_EBX); 210 | case REG_BX: regsTainted.push_front(REG_BX); 211 | case REG_BH: regsTainted.push_front(REG_BH); 212 | case REG_BL: regsTainted.push_front(REG_BL); 213 | break; 214 | 215 | case REG_RCX: regsTainted.push_front(REG_RCX); 216 | case REG_ECX: regsTainted.push_front(REG_ECX); 217 | case REG_CX: regsTainted.push_front(REG_CX); 218 | case REG_CH: regsTainted.push_front(REG_CH); 219 | case REG_CL: regsTainted.push_front(REG_CL); 220 | break; 221 | 222 | case REG_RDX: regsTainted.push_front(REG_RDX); 223 | case REG_EDX: regsTainted.push_front(REG_EDX); 224 | case REG_DX: regsTainted.push_front(REG_DX); 225 | case REG_DH: regsTainted.push_front(REG_DH); 226 | case REG_DL: regsTainted.push_front(REG_DL); 227 | break; 228 | 229 | case REG_RDI: regsTainted.push_front(REG_RDI); 230 | case REG_EDI: regsTainted.push_front(REG_EDI); 231 | case REG_DI: regsTainted.push_front(REG_DI); 232 | case REG_DIL: regsTainted.push_front(REG_DIL); 233 | break; 234 | 235 | case REG_RSI: regsTainted.push_front(REG_RSI); 236 | case REG_ESI: regsTainted.push_front(REG_ESI); 237 | case REG_SI: regsTainted.push_front(REG_SI); 238 | case REG_SIL: regsTainted.push_front(REG_SIL); 239 | break; 240 | 241 | default: 242 | std::cout << "\t\t\t" << REG_StringShort(reg) << " can't be tainted" << std::endl; 243 | return false; 244 | } 245 | std::cout << "\t\t\t" << REG_StringShort(reg) << " is now tainted" << std::endl; 246 | return true; 247 | } 248 | 249 | BOOL removeRegTainted(REG reg) 250 | { 251 | switch(reg){ 252 | 253 | case REG_RAX: regsTainted.remove(REG_RAX); 254 | case REG_EAX: regsTainted.remove(REG_EAX); 255 | case REG_AX: regsTainted.remove(REG_AX); 256 | case REG_AH: regsTainted.remove(REG_AH); 257 | case REG_AL: regsTainted.remove(REG_AL); 258 | break; 259 | 260 | case REG_RBX: regsTainted.remove(REG_RBX); 261 | case REG_EBX: regsTainted.remove(REG_EBX); 262 | case REG_BX: regsTainted.remove(REG_BX); 263 | case REG_BH: regsTainted.remove(REG_BH); 264 | case REG_BL: regsTainted.remove(REG_BL); 265 | break; 266 | 267 | case REG_RCX: regsTainted.remove(REG_RCX); 268 | case REG_ECX: regsTainted.remove(REG_ECX); 269 | case REG_CX: regsTainted.remove(REG_CX); 270 | case REG_CH: regsTainted.remove(REG_CH); 271 | case REG_CL: regsTainted.remove(REG_CL); 272 | break; 273 | 274 | case REG_RDX: regsTainted.remove(REG_RDX); 275 | case REG_EDX: regsTainted.remove(REG_EDX); 276 | case REG_DX: regsTainted.remove(REG_DX); 277 | case REG_DH: regsTainted.remove(REG_DH); 278 | case REG_DL: regsTainted.remove(REG_DL); 279 | break; 280 | 281 | case REG_RDI: regsTainted.remove(REG_RDI); 282 | case REG_EDI: regsTainted.remove(REG_EDI); 283 | case REG_DI: regsTainted.remove(REG_DI); 284 | case REG_DIL: regsTainted.remove(REG_DIL); 285 | break; 286 | 287 | case REG_RSI: regsTainted.remove(REG_RSI); 288 | case REG_ESI: regsTainted.remove(REG_ESI); 289 | case REG_SI: regsTainted.remove(REG_SI); 290 | case REG_SIL: regsTainted.remove(REG_SIL); 291 | break; 292 | 293 | default: 294 | return false; 295 | } 296 | std::cout << "\t\t\t" << REG_StringShort(reg) << " is now freed" << std::endl; 297 | return true; 298 | } 299 | 300 | VOID ReadMem(UINT64 insAddr, std::string insDis, UINT32 opCount, REG reg_r, UINT64 memOp, UINT64 sp) 301 | { 302 | list::iterator i; 303 | list::iterator i2; 304 | UINT64 addr = memOp; 305 | 306 | if (opCount != 2) 307 | return; 308 | 309 | for(i = addressTainted.begin(); i != addressTainted.end(); i++){ 310 | if (addr == *i){ 311 | std::cout << std::hex << "[READ in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 312 | taintReg(reg_r); 313 | return; 314 | } 315 | } 316 | if (checkAlreadyRegTainted(reg_r)){ 317 | std::cout << std::hex << "[READ in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 318 | removeRegTainted(reg_r); 319 | } 320 | } 321 | 322 | VOID WriteMem(UINT64 insAddr, std::string insDis, UINT32 opCount, REG reg_r, UINT64 memOp, UINT64 sp) 323 | { 324 | list::iterator i; 325 | list::iterator i2; 326 | UINT64 addr = memOp; 327 | 328 | if (opCount != 2) 329 | return; 330 | 331 | for(i = addressTainted.begin(); i != addressTainted.end(); i++){ 332 | if (addr == *i){ 333 | std::cout << std::hex << "[WRITE in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 334 | if (!REG_valid(reg_r) || !checkAlreadyRegTainted(reg_r)) 335 | removeMemTainted(addr); 336 | return ; 337 | } 338 | } 339 | if (checkAlreadyRegTainted(reg_r)){ 340 | std::cout << std::hex << "[WRITE in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 341 | addMemTainted(addr); 342 | } 343 | } 344 | 345 | VOID spreadRegTaint(UINT64 insAddr, std::string insDis, UINT32 opCount, REG reg_r, REG reg_w) 346 | { 347 | if (opCount != 2) 348 | return; 349 | 350 | if (REG_valid(reg_w)){ 351 | if (checkAlreadyRegTainted(reg_w) && (!REG_valid(reg_r) || !checkAlreadyRegTainted(reg_r))){ 352 | std::cout << "[SPREAD]\t\t" << insAddr << ": " << insDis << std::endl; 353 | std::cout << "\t\t\toutput: "<< REG_StringShort(reg_w) << " | input: " << (REG_valid(reg_r) ? REG_StringShort(reg_r) : "constant") << std::endl; 354 | removeRegTainted(reg_w); 355 | } 356 | else if (!checkAlreadyRegTainted(reg_w) && checkAlreadyRegTainted(reg_r)){ 357 | std::cout << "[SPREAD]\t\t" << insAddr << ": " << insDis << std::endl; 358 | std::cout << "\t\t\toutput: " << REG_StringShort(reg_w) << " | input: "<< REG_StringShort(reg_r) << std::endl; 359 | taintReg(reg_w); 360 | } 361 | } 362 | } 363 | 364 | VOID followData(UINT64 insAddr, std::string insDis, REG reg) 365 | { 366 | if (!REG_valid(reg)) 367 | return; 368 | 369 | if (checkAlreadyRegTainted(reg)){ 370 | std::cout << "[FOLLOW]\t\t" << insAddr << ": " << insDis << std::endl; 371 | } 372 | } 373 | 374 | VOID Instruction(INS ins, VOID *v) 375 | { 376 | if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsRead(ins, 0) && INS_OperandIsReg(ins, 0)){ 377 | INS_InsertCall( 378 | ins, IPOINT_BEFORE, (AFUNPTR)ReadMem, 379 | IARG_ADDRINT, INS_Address(ins), 380 | IARG_PTR, new string(INS_Disassemble(ins)), 381 | IARG_UINT32, INS_OperandCount(ins), 382 | IARG_UINT32, INS_OperandReg(ins, 0), 383 | IARG_MEMORYOP_EA, 0, 384 | IARG_REG_VALUE, REG_STACK_PTR, 385 | IARG_END); 386 | } 387 | else if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsWritten(ins, 0)){ 388 | INS_InsertCall( 389 | ins, IPOINT_BEFORE, (AFUNPTR)WriteMem, 390 | IARG_ADDRINT, INS_Address(ins), 391 | IARG_PTR, new string(INS_Disassemble(ins)), 392 | IARG_UINT32, INS_OperandCount(ins), 393 | IARG_UINT32, INS_OperandReg(ins, 1), 394 | IARG_MEMORYOP_EA, 0, 395 | IARG_REG_VALUE, REG_STACK_PTR, 396 | IARG_END); 397 | } 398 | else if (INS_OperandCount(ins) > 1 && INS_OperandIsReg(ins, 0)){ 399 | INS_InsertCall( 400 | ins, IPOINT_BEFORE, (AFUNPTR)spreadRegTaint, 401 | IARG_ADDRINT, INS_Address(ins), 402 | IARG_PTR, new string(INS_Disassemble(ins)), 403 | IARG_UINT32, INS_OperandCount(ins), 404 | IARG_UINT32, INS_RegR(ins, 0), 405 | IARG_UINT32, INS_RegW(ins, 0), 406 | IARG_END); 407 | } 408 | 409 | if (INS_OperandCount(ins) > 1 && INS_OperandIsReg(ins, 0)){ 410 | INS_InsertCall( 411 | ins, IPOINT_BEFORE, (AFUNPTR)followData, 412 | IARG_ADDRINT, INS_Address(ins), 413 | IARG_PTR, new string(INS_Disassemble(ins)), 414 | IARG_UINT32, INS_RegR(ins, 0), 415 | IARG_END); 416 | } 417 | } 418 | 419 | VOID checkFormatString(ADDRINT rdi) 420 | { 421 | list::iterator i; 422 | std::string content = std::string((const char *)rdi); 423 | 424 | std::cout << "[frmtstr] \t\tprintf() is called" << std::endl; 425 | std::cout << "[frmtstr] \t\tRDI content: " << content << std::endl; 426 | 427 | for(i = addressTainted.begin(); i != addressTainted.end(); i++){ 428 | if (rdi == *i){ 429 | std::cout << "[frmtstr] \t\tThe RDI memory area is tagged as tainted" << std::endl; 430 | if (content.find("%s") == string::npos) 431 | std::cout << "[frmtstr] \t\tThis printf is probably vulnerable" << std::endl; 432 | return; 433 | } 434 | } 435 | } 436 | 437 | VOID Image(IMG img, VOID *v) 438 | { 439 | RTN printfRtn = RTN_FindByName(img, "printf"); 440 | 441 | if (RTN_Valid(printfRtn)){ 442 | RTN_Open(printfRtn); 443 | 444 | RTN_InsertCall( 445 | printfRtn, 446 | IPOINT_BEFORE, (AFUNPTR)checkFormatString, 447 | IARG_REG_VALUE, REG_RDI, 448 | IARG_END); 449 | 450 | RTN_Close(printfRtn); 451 | } 452 | } 453 | 454 | static unsigned int tryksOpen; 455 | 456 | #define TRICKS(){if (tryksOpen++ == 0)return;} 457 | 458 | VOID Syscall_entry(THREADID thread_id, CONTEXT *ctx, SYSCALL_STANDARD std, void *v) 459 | { 460 | unsigned int i; 461 | UINT64 start, size; 462 | 463 | if (PIN_GetSyscallNumber(ctx, std) == __NR_read){ 464 | 465 | TRICKS(); /* tricks to ignore the first open */ 466 | 467 | start = static_cast((PIN_GetSyscallArgument(ctx, std, 1))); 468 | size = static_cast((PIN_GetSyscallArgument(ctx, std, 2))); 469 | 470 | for (i = 0; i < size; i++) 471 | addressTainted.push_back(start+i); 472 | 473 | std::cout << "[TAINT]\t\t\tbytes tainted from " << std::hex << "0x" << start << " to 0x" << start+size << " (via read)"<< std::endl; 474 | } 475 | } 476 | 477 | int main(int argc, char *argv[]) 478 | { 479 | PIN_InitSymbols(); 480 | if(PIN_Init(argc, argv)){ 481 | return Usage(); 482 | } 483 | 484 | PIN_SetSyntaxIntel(); 485 | IMG_AddInstrumentFunction(Image, 0); 486 | PIN_AddSyscallEntryFunction(Syscall_entry, 0); 487 | INS_AddInstrumentFunction(Instruction, 0); 488 | PIN_StartProgram(); 489 | 490 | return 0; 491 | } 492 | 493 | -------------------------------------------------------------------------------- /FormatStringDetection/makefile: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # DO NOT EDIT THIS FILE! 4 | # 5 | ############################################################## 6 | 7 | # If the tool is built out of the kit, PIN_ROOT must be specified in the make invocation and point to the kit root. 8 | ifdef PIN_ROOT 9 | CONFIG_ROOT := $(PIN_ROOT)/source/tools/Config 10 | else 11 | CONFIG_ROOT := ../Config 12 | endif 13 | include $(CONFIG_ROOT)/makefile.config 14 | include makefile.rules 15 | include $(TOOLS_ROOT)/Config/makefile.default.rules 16 | 17 | ############################################################## 18 | # 19 | # DO NOT EDIT THIS FILE! 20 | # 21 | ############################################################## 22 | -------------------------------------------------------------------------------- /FormatStringDetection/makefile.rules: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # This file includes all the test targets as well as all the 4 | # non-default build rules and test recipes. 5 | # 6 | ############################################################## 7 | 8 | 9 | ############################################################## 10 | # 11 | # Test targets 12 | # 13 | ############################################################## 14 | 15 | ###### Place all generic definitions here ###### 16 | 17 | # This defines tests which run tools of the same name. This is simply for convenience to avoid 18 | # defining the test name twice (once in TOOL_ROOTS and again in TEST_ROOTS). 19 | # Tests defined here should not be defined in TOOL_ROOTS and TEST_ROOTS. 20 | TEST_TOOL_ROOTS := frmtstr 21 | 22 | # This defines the tests to be run that were not already defined in TEST_TOOL_ROOTS. 23 | TEST_ROOTS := 24 | 25 | # This defines a list of tests that should run in the "short" sanity. Tests in this list must also 26 | # appear either in the TEST_TOOL_ROOTS or the TEST_ROOTS list. 27 | # If the entire directory should be tested in sanity, assign TEST_TOOL_ROOTS and TEST_ROOTS to the 28 | # SANITY_SUBSET variable in the tests section below (see example in makefile.rules.tmpl). 29 | SANITY_SUBSET := 30 | 31 | # This defines the tools which will be run during the the tests, and were not already defined in 32 | # TEST_TOOL_ROOTS. 33 | TOOL_ROOTS := 34 | 35 | # This defines the static analysis tools which will be run during the the tests. They should not 36 | # be defined in TEST_TOOL_ROOTS. If a test with the same name exists, it should be defined in 37 | # TEST_ROOTS. 38 | # Note: Static analysis tools are in fact executables linked with the Pin Static Analysis Library. 39 | # This library provides a subset of the Pin APIs which allows the tool to perform static analysis 40 | # of an application or dll. Pin itself is not used when this tool runs. 41 | SA_TOOL_ROOTS := 42 | 43 | # This defines all the applications that will be run during the tests. 44 | APP_ROOTS := 45 | 46 | # This defines any additional object files that need to be compiled. 47 | OBJECT_ROOTS := 48 | 49 | # This defines any additional dlls (shared objects), other than the pintools, that need to be compiled. 50 | DLL_ROOTS := 51 | 52 | # This defines any static libraries (archives), that need to be built. 53 | LIB_ROOTS := 54 | 55 | 56 | ############################################################## 57 | # 58 | # Test recipes 59 | # 60 | ############################################################## 61 | 62 | # This section contains recipes for tests other than the default. 63 | # See makefile.default.rules for the default test rules. 64 | # All tests in this section should adhere to the naming convention: .test 65 | 66 | 67 | ############################################################## 68 | # 69 | # Build rules 70 | # 71 | ############################################################## 72 | 73 | # This section contains the build rules for all binaries that have special build rules. 74 | # See makefile.default.rules for the default build rules. 75 | -------------------------------------------------------------------------------- /FormatStringDetection/test.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | void foo(char *buf) 9 | { 10 | unsigned int i; 11 | char *ptr; 12 | 13 | if (!(ptr = malloc(8))) 14 | return; 15 | 16 | for (i = 0; i < 8; i++) 17 | ptr[i] = buf[i]; /* spread the taint to another area */ 18 | 19 | printf(ptr); /* warn format string */ 20 | } 21 | 22 | int main(int ac, char **av) 23 | { 24 | int fd; 25 | char *buf; 26 | 27 | if (!(buf = malloc(8))) 28 | return -1; 29 | 30 | fd = open("./file.txt", O_RDONLY); 31 | read(fd, buf, 8); /* The range [buff, buff+32] is tainted */ 32 | close(fd); 33 | 34 | foo(buf); 35 | } 36 | 37 | -------------------------------------------------------------------------------- /InMemoryFuzzing/InMemoryFuzzing.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // BEGIN_LEGAL 3 | // Intel Open Source License 4 | // 5 | // Copyright (c) 2002-2013 Intel Corporation. All rights reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are 9 | // met: 10 | // 11 | // Redistributions of source code must retain the above copyright notice, 12 | // this list of conditions and the following disclaimer. Redistributions 13 | // in binary form must reproduce the above copyright notice, this list of 14 | // conditions and the following disclaimer in the documentation and/or 15 | // other materials provided with the distribution. Neither the name of 16 | // the Intel Corporation nor the names of its contributors may be used to 17 | // endorse or promote products derived from this software without 18 | // specific prior written permission. 19 | // 20 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | // ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR 24 | // ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | // END_LEGAL 32 | // 33 | // ------------------------------------------------------------------------ 34 | // 35 | // Jonathan Salwan - 2013-08-17 36 | // 37 | // http://shell-storm.org 38 | // http://twitter.com/JonathanSalwan 39 | // 40 | // Note: In-Memory Fuzzing with Pin 41 | // http://shell-storm.org/blog/In-Memory-fuzzing-with-Pin/ 42 | // 43 | // Vulnerable example: 44 | // 45 | // 400584 : 46 | // 400584: 55 push rbp 47 | // 400585: 48 89 e5 mov rbp,rsp 48 | // 400588: 48 83 ec 10 sub rsp,0x10 49 | // 40058c: 89 7d fc mov DWORD PTR [rbp-0x4],edi 50 | // 40058f: 48 89 75 f0 mov QWORD PTR [rbp-0x10],rsi 51 | // 400593: 8b 45 fc mov eax,DWORD PTR [rbp-0x4] 52 | // 400596: 48 98 cdqe 53 | // 400598: 48 03 45 f0 add rax,QWORD PTR [rbp-0x10] 54 | // 40059c: 0f b6 00 movzx eax,BYTE PTR [rax] 55 | // 40059f: 0f be d0 movsx edx,al 56 | // 4005a2: b8 2c 07 40 00 mov eax,0x40072c 57 | // 4005a7: 89 d6 mov esi,edx 58 | // 4005a9: 48 89 c7 mov rdi,rax 59 | // 4005ac: b8 00 00 00 00 mov eax,0x0 60 | // 4005b1: e8 ba fe ff ff call 400470 61 | // 4005b6: c9 leave 62 | // 4005b7: c3 ret 63 | // 64 | // Syntax based on the above code: 65 | // $ ../../../pin -t ./obj-intel64/InMemoryFuzzing.so -start 0x400584 -end 0x4005b7 -reg rdi -fuzzingType inc -maxValue 0x3000 -- ./test 1 66 | // 67 | // The output will be like that: 68 | // [...] 69 | // [Save Context] 70 | // [CONTEXT]=---------------------------------------------------------- 71 | // RAX = 0000000000000002 RBX = 0000000000000000 RCX = 00007fffb8f55170 72 | // RDX = 00007fffb8f542e0 RDI = 0000000000001d20 RSI = 00007fffb8f542e0 73 | // RBP = 00007fffb8f54310 RSP = 00007fffb8f542c8 RIP = 0000000000400585 74 | // +------------------------------------------------------------------- 75 | // +--> 400585: mov rbp, rsp 76 | // +--> 400588: sub rsp, 0x10 77 | // +--> 40058c: mov dword ptr [rbp-0x4], edi 78 | // +--> 40058f: mov qword ptr [rbp-0x10], rsi 79 | // +--> 400593: mov eax, dword ptr [rbp-0x4] 80 | // +--> 400596: cdqe 81 | // +--> 400598: add rax, qword ptr [rbp-0x10] 82 | // +--> 40059c: movzx eax, byte ptr [rax] 83 | // 84 | // SIGSEGV received 85 | // [SIGSGV]=---------------------------------------------------------- 86 | // RAX = 00007fffb8f56000 RBX = 0000000000000000 RCX = 00007fffb8f55170 87 | // RDX = 00007fffb8f542e0 RDI = 0000000000001d20 RSI = 00007fffb8f542e0 88 | // RBP = 00007fffb8f542c8 RSP = 00007fffb8f542b8 RIP = 000000000040059c 89 | // +------------------------------------------------------------------- 90 | // 91 | // 92 | // We got a SIGSEGV if RDI = 0x1d20 93 | // 94 | 95 | #include "pin.H" 96 | #include 97 | #include 98 | #include 99 | #include 100 | #include 101 | #include 102 | #include 103 | #include 104 | 105 | #define LOCKED 1 106 | #define UNLOCKED !LOCKED 107 | 108 | #define CONTEXT_FLG 0 109 | #define SIGSEGV_FLG 1 110 | 111 | struct memoryInput 112 | { 113 | ADDRINT address; 114 | UINT64 value; 115 | }; 116 | 117 | struct regRef 118 | { 119 | std::string name; 120 | LEVEL_BASE::REG ref; 121 | }; 122 | 123 | static UINT32 _lock = LOCKED; 124 | std::list memInput; 125 | CONTEXT snapshot; 126 | 127 | /* Required arg */ 128 | KNOB KnobStart(KNOB_MODE_WRITEONCE, "pintool", "start", "0", "The start address of the fuzzing area"); 129 | KNOB KnobEnd(KNOB_MODE_WRITEONCE, "pintool", "end", "0", "The end address of the fuzzing area"); 130 | KNOB KnobREG(KNOB_MODE_WRITEONCE, "pintool", "reg", "none", "The register which will be fuzzed"); 131 | 132 | /* Optinal arg */ 133 | KNOB KnobStartValue(KNOB_MODE_WRITEONCE, "pintool", "startValue", "0", "The start value"); 134 | KNOB KnobMaxValue(KNOB_MODE_WRITEONCE, "pintool", "maxValue", "0xffffffff", "The end value"); 135 | KNOB KnobFuzzType(KNOB_MODE_WRITEONCE, "pintool", "fuzzingType", "none", "Type of fuzzing: incremental or random"); 136 | 137 | static struct regRef regsRef[] = 138 | { 139 | {"rax", LEVEL_BASE::REG_RAX}, 140 | {"rbx", LEVEL_BASE::REG_RBX}, 141 | {"rcx", LEVEL_BASE::REG_RCX}, 142 | {"rdx", LEVEL_BASE::REG_RDX}, 143 | {"rdi", LEVEL_BASE::REG_RDI}, 144 | {"rsi", LEVEL_BASE::REG_RSI}, 145 | {"eax", LEVEL_BASE::REG_EAX}, 146 | {"ebx", LEVEL_BASE::REG_EBX}, 147 | {"ecx", LEVEL_BASE::REG_ECX}, 148 | {"edx", LEVEL_BASE::REG_EDX}, 149 | {"edi", LEVEL_BASE::REG_EDI}, 150 | {"esi", LEVEL_BASE::REG_ESI}, 151 | {"ah", LEVEL_BASE::REG_AH}, 152 | {"bh", LEVEL_BASE::REG_BH}, 153 | {"ch", LEVEL_BASE::REG_CH}, 154 | {"dh", LEVEL_BASE::REG_DH}, 155 | {"al", LEVEL_BASE::REG_AL}, 156 | {"bl", LEVEL_BASE::REG_BL}, 157 | {"cl", LEVEL_BASE::REG_CL}, 158 | {"dl", LEVEL_BASE::REG_DL}, 159 | {"dil", LEVEL_BASE::REG_DIL}, 160 | {"sil", LEVEL_BASE::REG_SIL}, 161 | {"", REG_INVALID()} 162 | }; 163 | 164 | INT32 Usage() 165 | { 166 | std::cerr << "In-Memory Fuzzing tool" << std::endl; 167 | cerr << endl << KNOB_BASE::StringKnobSummary() << endl; 168 | return -1; 169 | } 170 | 171 | VOID displayCurrentContext(CONTEXT *ctx, UINT32 flag) 172 | { 173 | std::cout << "[" << (flag == CONTEXT_FLG ? "CONTEXT" : "SIGSGV") 174 | << "]=----------------------------------------------------------" << std::endl; 175 | std::cout << std::hex << std::internal << std::setfill('0') 176 | << "RAX = " << std::setw(16) << PIN_GetContextReg(ctx, LEVEL_BASE::REG_RAX) << " " 177 | << "RBX = " << std::setw(16) << PIN_GetContextReg(ctx, LEVEL_BASE::REG_RBX) << " " 178 | << "RCX = " << std::setw(16) << PIN_GetContextReg(ctx, LEVEL_BASE::REG_RCX) << std::endl 179 | << "RDX = " << std::setw(16) << PIN_GetContextReg(ctx, LEVEL_BASE::REG_RDX) << " " 180 | << "RDI = " << std::setw(16) << PIN_GetContextReg(ctx, LEVEL_BASE::REG_RDI) << " " 181 | << "RSI = " << std::setw(16) << PIN_GetContextReg(ctx, LEVEL_BASE::REG_RSI) << std::endl 182 | << "RBP = " << std::setw(16) << PIN_GetContextReg(ctx, LEVEL_BASE::REG_RBP) << " " 183 | << "RSP = " << std::setw(16) << PIN_GetContextReg(ctx, LEVEL_BASE::REG_RSP) << " " 184 | << "RIP = " << std::setw(16) << PIN_GetContextReg(ctx, LEVEL_BASE::REG_RIP) << std::endl; 185 | std::cout << "+-------------------------------------------------------------------" << std::endl; 186 | } 187 | 188 | static UINT32 fuzzValue; 189 | 190 | VOID randomizeREG(CONTEXT *ctx, ADDRINT nextInsAddr) 191 | { 192 | UINT32 i; 193 | 194 | if (KnobFuzzType.Value() == "random"){ 195 | sleep(1); 196 | srand(time(NULL)); 197 | fuzzValue = (rand() % (KnobMaxValue.Value() - KnobStartValue.Value())) + KnobStartValue.Value(); 198 | } 199 | else if (KnobFuzzType.Value() == "inc"){ 200 | fuzzValue++; 201 | } 202 | 203 | for (i = 0; !(regsRef[i].name.empty()); i++){ 204 | if (regsRef[i].name == KnobREG.Value()){ 205 | PIN_SetContextReg(ctx, regsRef[i].ref, fuzzValue); 206 | break; 207 | } 208 | } 209 | 210 | PIN_SetContextReg(ctx, LEVEL_BASE::REG_RIP, nextInsAddr); 211 | } 212 | 213 | VOID restoreMemory(void) 214 | { 215 | list::iterator i; 216 | 217 | for(i = memInput.begin(); i != memInput.end(); ++i){ 218 | *(reinterpret_cast(i->address)) = i->value; 219 | } 220 | memInput.clear(); 221 | } 222 | 223 | VOID insCallBack(ADDRINT insAddr, std::string insDis, CONTEXT *ctx, ADDRINT nextInsAddr) 224 | { 225 | if (nextInsAddr == KnobStart.Value()){ 226 | if (fuzzValue >= KnobMaxValue.Value()){ 227 | std::cout << "[In-Memory fuzzing stoped. The program continue with the original context]" << std::endl; 228 | displayCurrentContext(ctx, CONTEXT_FLG); 229 | return PIN_RemoveInstrumentation(); 230 | } 231 | std::cout << "[Save Context]" << std::endl; 232 | PIN_SaveContext(ctx, &snapshot); 233 | randomizeREG(ctx, nextInsAddr); 234 | displayCurrentContext(ctx, CONTEXT_FLG); 235 | _lock = UNLOCKED; 236 | PIN_ExecuteAt(ctx); 237 | } 238 | 239 | if (_lock == LOCKED) 240 | return; 241 | 242 | std::cout << "+--> " << std::hex << insAddr << ": " << insDis << std::endl; 243 | 244 | if (insAddr == KnobEnd.Value()){ 245 | _lock = LOCKED; 246 | std::cout << "[Restore Context]" << std::endl; 247 | PIN_SaveContext(&snapshot, ctx); 248 | restoreMemory(); 249 | PIN_ExecuteAt(ctx); 250 | } 251 | } 252 | 253 | VOID WriteMem(ADDRINT insAddr, std::string insDis, ADDRINT memOp) 254 | { 255 | struct memoryInput elem; 256 | ADDRINT addr = memOp; 257 | 258 | if (_lock == LOCKED) 259 | return; 260 | 261 | elem.address = addr; 262 | elem.value = *(reinterpret_cast(addr)); 263 | memInput.push_back(elem); 264 | } 265 | 266 | VOID Instruction(INS ins, VOID *v) 267 | { 268 | PIN_LockClient(); 269 | IMG img = IMG_FindByAddress(INS_Address(ins)); 270 | PIN_UnlockClient(); 271 | 272 | if (IMG_Valid(img) && IMG_IsMainExecutable(img)){ 273 | INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)insCallBack, 274 | IARG_ADDRINT, INS_Address(ins), 275 | IARG_PTR, new string(INS_Disassemble(ins)), 276 | IARG_CONTEXT, 277 | IARG_ADDRINT, INS_NextAddress(ins), 278 | IARG_END); 279 | } 280 | 281 | if (INS_MemoryOperandIsWritten(ins, 0)){ 282 | INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)WriteMem, 283 | IARG_ADDRINT, INS_Address(ins), 284 | IARG_PTR, new string(INS_Disassemble(ins)), 285 | IARG_MEMORYOP_EA, 0, 286 | IARG_END); 287 | } 288 | } 289 | 290 | BOOL catchSignal(THREADID tid, INT32 sig, CONTEXT *ctx, BOOL hasHandler, const EXCEPTION_INFO *pExceptInfo, VOID *v) 291 | { 292 | std::cout << std::endl << std::endl << "/!\\ SIGSEGV received /!\\" << std::endl; 293 | displayCurrentContext(ctx, SIGSEGV_FLG); 294 | return true; 295 | } 296 | 297 | int main(int argc, char *argv[]) 298 | { 299 | if(PIN_Init(argc, argv)){ 300 | return Usage(); 301 | } 302 | 303 | if (!KnobStart.Value() || !KnobEnd.Value() || !KnobREG.Value().empty()) 304 | return Usage(); 305 | 306 | if (KnobStartValue.Value() > KnobMaxValue.Value()) 307 | return Usage(); 308 | 309 | fuzzValue = KnobStartValue.Value() - 1; 310 | 311 | PIN_SetSyntaxIntel(); 312 | PIN_InterceptSignal(SIGSEGV, catchSignal, 0); 313 | INS_AddInstrumentFunction(Instruction, 0); 314 | PIN_StartProgram(); 315 | 316 | return 0; 317 | } 318 | 319 | -------------------------------------------------------------------------------- /InMemoryFuzzing/dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/InMemoryFuzzing/dump -------------------------------------------------------------------------------- /InMemoryFuzzing/makefile: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # DO NOT EDIT THIS FILE! 4 | # 5 | ############################################################## 6 | 7 | # If the tool is built out of the kit, PIN_ROOT must be specified in the make invocation and point to the kit root. 8 | ifdef PIN_ROOT 9 | CONFIG_ROOT := $(PIN_ROOT)/source/tools/Config 10 | else 11 | CONFIG_ROOT := ../Config 12 | endif 13 | include $(CONFIG_ROOT)/makefile.config 14 | include makefile.rules 15 | include $(TOOLS_ROOT)/Config/makefile.default.rules 16 | 17 | ############################################################## 18 | # 19 | # DO NOT EDIT THIS FILE! 20 | # 21 | ############################################################## 22 | -------------------------------------------------------------------------------- /InMemoryFuzzing/makefile.rules: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # This file includes all the test targets as well as all the 4 | # non-default build rules and test recipes. 5 | # 6 | ############################################################## 7 | 8 | 9 | ############################################################## 10 | # 11 | # Test targets 12 | # 13 | ############################################################## 14 | 15 | ###### Place all generic definitions here ###### 16 | 17 | # This defines tests which run tools of the same name. This is simply for convenience to avoid 18 | # defining the test name twice (once in TOOL_ROOTS and again in TEST_ROOTS). 19 | # Tests defined here should not be defined in TOOL_ROOTS and TEST_ROOTS. 20 | TEST_TOOL_ROOTS := InMemoryFuzzing 21 | 22 | # This defines the tests to be run that were not already defined in TEST_TOOL_ROOTS. 23 | TEST_ROOTS := 24 | 25 | # This defines a list of tests that should run in the "short" sanity. Tests in this list must also 26 | # appear either in the TEST_TOOL_ROOTS or the TEST_ROOTS list. 27 | # If the entire directory should be tested in sanity, assign TEST_TOOL_ROOTS and TEST_ROOTS to the 28 | # SANITY_SUBSET variable in the tests section below (see example in makefile.rules.tmpl). 29 | SANITY_SUBSET := 30 | 31 | # This defines the tools which will be run during the the tests, and were not already defined in 32 | # TEST_TOOL_ROOTS. 33 | TOOL_ROOTS := 34 | 35 | # This defines the static analysis tools which will be run during the the tests. They should not 36 | # be defined in TEST_TOOL_ROOTS. If a test with the same name exists, it should be defined in 37 | # TEST_ROOTS. 38 | # Note: Static analysis tools are in fact executables linked with the Pin Static Analysis Library. 39 | # This library provides a subset of the Pin APIs which allows the tool to perform static analysis 40 | # of an application or dll. Pin itself is not used when this tool runs. 41 | SA_TOOL_ROOTS := 42 | 43 | # This defines all the applications that will be run during the tests. 44 | APP_ROOTS := 45 | 46 | # This defines any additional object files that need to be compiled. 47 | OBJECT_ROOTS := 48 | 49 | # This defines any additional dlls (shared objects), other than the pintools, that need to be compiled. 50 | DLL_ROOTS := 51 | 52 | # This defines any static libraries (archives), that need to be built. 53 | LIB_ROOTS := 54 | 55 | 56 | ############################################################## 57 | # 58 | # Test recipes 59 | # 60 | ############################################################## 61 | 62 | # This section contains recipes for tests other than the default. 63 | # See makefile.default.rules for the default test rules. 64 | # All tests in this section should adhere to the naming convention: .test 65 | 66 | 67 | ############################################################## 68 | # 69 | # Build rules 70 | # 71 | ############################################################## 72 | 73 | # This section contains the build rules for all binaries that have special build rules. 74 | # See makefile.default.rules for the default build rules. 75 | -------------------------------------------------------------------------------- /InMemoryFuzzing/pin.log: -------------------------------------------------------------------------------- 1 | Pin 2.12 kit 58423 2 | E: Register sil is NOT supported for PIN_GetContextReg/PIN_SetContextReg 3 | -------------------------------------------------------------------------------- /InMemoryFuzzing/pintool.log: -------------------------------------------------------------------------------- 1 | Pin 2.12 kit 58423 2 | A: Source/pin/pin/image.cpp:IMG_IsMainExecutable:IMG_IsMainExecutable:324: The img passed to IMG_IsMainExecutable() is stale 3 | 4 | -------------------------------------------------------------------------------- /InMemoryFuzzing/test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/InMemoryFuzzing/test -------------------------------------------------------------------------------- /InMemoryFuzzing/test.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Jonathan Salwan - 2013-08-14 3 | ** 4 | ** http://shell-storm.org 5 | ** http://twitter.com/JonathanSalwan 6 | ** 7 | ** This program is free software: you can redistribute it and/or modify 8 | ** it under the terms of the GNU General Public License as published by 9 | ** the Free Software Foundation, either version 3 of the License, or 10 | ** (at your option) any later version. 11 | */ 12 | 13 | #include 14 | 15 | int foo(int i, char *tab) 16 | { 17 | if (i > 0 && i < 0x3000){ 18 | printf("%c\n", tab[i]); 19 | return 0; 20 | } 21 | return -1; 22 | } 23 | 24 | int main(int ac, const char *av[]) 25 | { 26 | char tab[] = "qwertyuiopasdfghjklzxcvbnm1234567890"; 27 | 28 | if (ac == 2) 29 | foo(atoi(av[1]), tab); 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /LoopDetectionInstCounter/loop.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Jonathan Salwan - 2013-08-13 3 | // 4 | // http://shell-storm.org 5 | // http://twitter.com/JonathanSalwan 6 | // 7 | // Note: Pin tool - Simple loop detection via the instruction counter. 8 | // 9 | 10 | #include "pin.H" 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define LOCKED 1 17 | #define UNLOCKED !LOCKED 18 | 19 | static UINT32 _lockAnalysis = !LOCKED; /* unlock -> without sym */ 20 | static UINT16 _tabAddr[0x10000]; 21 | static std::string _tabStr[0x10000]; 22 | 23 | INT32 Usage() 24 | { 25 | std::cerr << "Foo test" << std::endl; 26 | return -1; 27 | } 28 | 29 | VOID insCallBack(UINT64 insAddr, std::string insDis) 30 | { 31 | if (_lockAnalysis) 32 | return ; 33 | 34 | if (insAddr > 0x700000000000) 35 | return; 36 | 37 | if (_tabAddr[insAddr ^ 0x400000] == 0xffff) 38 | return; 39 | 40 | _tabAddr[insAddr ^ 0x400000] += 1; 41 | _tabStr[insAddr ^ 0x400000] = insDis; 42 | 43 | } 44 | 45 | VOID Instruction(INS ins, VOID *v) 46 | { 47 | INS_InsertCall( 48 | ins, IPOINT_BEFORE, (AFUNPTR)insCallBack, 49 | IARG_ADDRINT, INS_Address(ins), 50 | IARG_PTR, new string(INS_Disassemble(ins)), 51 | IARG_END); 52 | } 53 | 54 | VOID unlockAnalysis(void) 55 | { 56 | _lockAnalysis = UNLOCKED; 57 | } 58 | 59 | VOID lockAnalysis(void) 60 | { 61 | _lockAnalysis = LOCKED; 62 | } 63 | 64 | VOID Image(IMG img, VOID *v) 65 | { 66 | RTN mainRtn = RTN_FindByName(img, "main"); 67 | 68 | if (RTN_Valid(mainRtn)){ 69 | RTN_Open(mainRtn); 70 | RTN_InsertCall(mainRtn, IPOINT_BEFORE, (AFUNPTR)unlockAnalysis, IARG_END); 71 | RTN_InsertCall(mainRtn, IPOINT_AFTER, (AFUNPTR)lockAnalysis, IARG_END); 72 | RTN_Close(mainRtn); 73 | } 74 | } 75 | 76 | VOID Fini(INT32 code, VOID *v) 77 | { 78 | UINT32 i; 79 | 80 | std::cout << "Addr\tNumber\tDisass" << std::endl; 81 | for (i = 0; i < 0x10000; i++){ 82 | if (_tabAddr[i]) 83 | std::cout << std::hex << (0x400000 + i) << "\t" << std::dec << _tabAddr[i] << "\t" << _tabStr[i] << std::endl; 84 | } 85 | } 86 | 87 | int main(int argc, char *argv[]) 88 | { 89 | PIN_InitSymbols(); 90 | if(PIN_Init(argc, argv)){ 91 | return Usage(); 92 | } 93 | 94 | PIN_SetSyntaxIntel(); 95 | //IMG_AddInstrumentFunction(Image, 0); 96 | INS_AddInstrumentFunction(Instruction, 0); 97 | PIN_AddFiniFunction(Fini, 0); 98 | PIN_StartProgram(); 99 | 100 | return 0; 101 | } 102 | 103 | -------------------------------------------------------------------------------- /LoopDetectionInstCounter/makefile: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # DO NOT EDIT THIS FILE! 4 | # 5 | ############################################################## 6 | 7 | # If the tool is built out of the kit, PIN_ROOT must be specified in the make invocation and point to the kit root. 8 | ifdef PIN_ROOT 9 | CONFIG_ROOT := $(PIN_ROOT)/source/tools/Config 10 | else 11 | CONFIG_ROOT := ../Config 12 | endif 13 | include $(CONFIG_ROOT)/makefile.config 14 | include makefile.rules 15 | include $(TOOLS_ROOT)/Config/makefile.default.rules 16 | 17 | ############################################################## 18 | # 19 | # DO NOT EDIT THIS FILE! 20 | # 21 | ############################################################## 22 | -------------------------------------------------------------------------------- /LoopDetectionInstCounter/makefile.rules: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # This file includes all the test targets as well as all the 4 | # non-default build rules and test recipes. 5 | # 6 | ############################################################## 7 | 8 | 9 | ############################################################## 10 | # 11 | # Test targets 12 | # 13 | ############################################################## 14 | 15 | ###### Place all generic definitions here ###### 16 | 17 | # This defines tests which run tools of the same name. This is simply for convenience to avoid 18 | # defining the test name twice (once in TOOL_ROOTS and again in TEST_ROOTS). 19 | # Tests defined here should not be defined in TOOL_ROOTS and TEST_ROOTS. 20 | TEST_TOOL_ROOTS := loop 21 | 22 | # This defines the tests to be run that were not already defined in TEST_TOOL_ROOTS. 23 | TEST_ROOTS := 24 | 25 | # This defines a list of tests that should run in the "short" sanity. Tests in this list must also 26 | # appear either in the TEST_TOOL_ROOTS or the TEST_ROOTS list. 27 | # If the entire directory should be tested in sanity, assign TEST_TOOL_ROOTS and TEST_ROOTS to the 28 | # SANITY_SUBSET variable in the tests section below (see example in makefile.rules.tmpl). 29 | SANITY_SUBSET := 30 | 31 | # This defines the tools which will be run during the the tests, and were not already defined in 32 | # TEST_TOOL_ROOTS. 33 | TOOL_ROOTS := 34 | 35 | # This defines the static analysis tools which will be run during the the tests. They should not 36 | # be defined in TEST_TOOL_ROOTS. If a test with the same name exists, it should be defined in 37 | # TEST_ROOTS. 38 | # Note: Static analysis tools are in fact executables linked with the Pin Static Analysis Library. 39 | # This library provides a subset of the Pin APIs which allows the tool to perform static analysis 40 | # of an application or dll. Pin itself is not used when this tool runs. 41 | SA_TOOL_ROOTS := 42 | 43 | # This defines all the applications that will be run during the tests. 44 | APP_ROOTS := 45 | 46 | # This defines any additional object files that need to be compiled. 47 | OBJECT_ROOTS := 48 | 49 | # This defines any additional dlls (shared objects), other than the pintools, that need to be compiled. 50 | DLL_ROOTS := 51 | 52 | # This defines any static libraries (archives), that need to be built. 53 | LIB_ROOTS := 54 | 55 | 56 | ############################################################## 57 | # 58 | # Test recipes 59 | # 60 | ############################################################## 61 | 62 | # This section contains recipes for tests other than the default. 63 | # See makefile.default.rules for the default test rules. 64 | # All tests in this section should adhere to the naming convention: .test 65 | 66 | 67 | ############################################################## 68 | # 69 | # Build rules 70 | # 71 | ############################################################## 72 | 73 | # This section contains the build rules for all binaries that have special build rules. 74 | # See makefile.default.rules for the default build rules. 75 | -------------------------------------------------------------------------------- /LoopDetectionInstCounter/test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/LoopDetectionInstCounter/test -------------------------------------------------------------------------------- /LoopDetectionInstCounter/test.c: -------------------------------------------------------------------------------- 1 | 2 | int main(int ac, char **av) 3 | { 4 | int i, x = 0; 5 | 6 | for (i = 0; i < 10; i++) 7 | x += i * 2; 8 | return x; 9 | } 10 | -------------------------------------------------------------------------------- /ObsoleteStackFrameAccessDetection/Taint.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Jonathan Salwan - Copyright (C) 2013-08 3 | // 4 | // http://shell-storm.org 5 | // http://twitter.com/JonathanSalwan 6 | // 7 | // Note: Example 4 - http://shell-storm.org/blog/Taint-analysis-with-Pin/ 8 | // Detect a use after free vulnerability via a old stack frame 9 | // 10 | 11 | #include "pin.H" 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | std::list addressTainted; 18 | std::list regsTainted; 19 | 20 | INT32 Usage() 21 | { 22 | cerr << "Ex 4" << endl; 23 | return -1; 24 | } 25 | 26 | bool checkAlreadyRegTainted(REG reg) 27 | { 28 | list::iterator i; 29 | 30 | for(i = regsTainted.begin(); i != regsTainted.end(); i++){ 31 | if (*i == reg){ 32 | return true; 33 | } 34 | } 35 | return false; 36 | } 37 | 38 | VOID removeMemTainted(UINT64 addr) 39 | { 40 | addressTainted.remove(addr); 41 | std::cout << std::hex << "\t\t\t" << addr << " is now freed" << std::endl; 42 | } 43 | 44 | VOID addMemTainted(UINT64 addr) 45 | { 46 | addressTainted.push_back(addr); 47 | std::cout << std::hex << "\t\t\t" << addr << " is now tainted" << std::endl; 48 | } 49 | 50 | bool taintReg(REG reg) 51 | { 52 | if (checkAlreadyRegTainted(reg) == true){ 53 | std::cout << "\t\t\t" << REG_StringShort(reg) << " is already tainted" << std::endl; 54 | return false; 55 | } 56 | 57 | switch(reg){ 58 | 59 | case REG_RAX: regsTainted.push_front(REG_RAX); 60 | case REG_EAX: regsTainted.push_front(REG_EAX); 61 | case REG_AX: regsTainted.push_front(REG_AX); 62 | case REG_AH: regsTainted.push_front(REG_AH); 63 | case REG_AL: regsTainted.push_front(REG_AL); 64 | break; 65 | 66 | case REG_RBX: regsTainted.push_front(REG_RBX); 67 | case REG_EBX: regsTainted.push_front(REG_EBX); 68 | case REG_BX: regsTainted.push_front(REG_BX); 69 | case REG_BH: regsTainted.push_front(REG_BH); 70 | case REG_BL: regsTainted.push_front(REG_BL); 71 | break; 72 | 73 | case REG_RCX: regsTainted.push_front(REG_RCX); 74 | case REG_ECX: regsTainted.push_front(REG_ECX); 75 | case REG_CX: regsTainted.push_front(REG_CX); 76 | case REG_CH: regsTainted.push_front(REG_CH); 77 | case REG_CL: regsTainted.push_front(REG_CL); 78 | break; 79 | 80 | case REG_RDX: regsTainted.push_front(REG_RDX); 81 | case REG_EDX: regsTainted.push_front(REG_EDX); 82 | case REG_DX: regsTainted.push_front(REG_DX); 83 | case REG_DH: regsTainted.push_front(REG_DH); 84 | case REG_DL: regsTainted.push_front(REG_DL); 85 | break; 86 | 87 | case REG_RDI: regsTainted.push_front(REG_RDI); 88 | case REG_EDI: regsTainted.push_front(REG_EDI); 89 | case REG_DI: regsTainted.push_front(REG_DI); 90 | case REG_DIL: regsTainted.push_front(REG_DIL); 91 | break; 92 | 93 | case REG_RSI: regsTainted.push_front(REG_RSI); 94 | case REG_ESI: regsTainted.push_front(REG_ESI); 95 | case REG_SI: regsTainted.push_front(REG_SI); 96 | case REG_SIL: regsTainted.push_front(REG_SIL); 97 | break; 98 | 99 | default: 100 | std::cout << "\t\t\t" << REG_StringShort(reg) << " can't be tainted" << std::endl; 101 | return false; 102 | } 103 | std::cout << "\t\t\t" << REG_StringShort(reg) << " is now tainted" << std::endl; 104 | return true; 105 | } 106 | 107 | bool removeRegTainted(REG reg) 108 | { 109 | switch(reg){ 110 | 111 | case REG_RAX: regsTainted.remove(REG_RAX); 112 | case REG_EAX: regsTainted.remove(REG_EAX); 113 | case REG_AX: regsTainted.remove(REG_AX); 114 | case REG_AH: regsTainted.remove(REG_AH); 115 | case REG_AL: regsTainted.remove(REG_AL); 116 | break; 117 | 118 | case REG_RBX: regsTainted.remove(REG_RBX); 119 | case REG_EBX: regsTainted.remove(REG_EBX); 120 | case REG_BX: regsTainted.remove(REG_BX); 121 | case REG_BH: regsTainted.remove(REG_BH); 122 | case REG_BL: regsTainted.remove(REG_BL); 123 | break; 124 | 125 | case REG_RCX: regsTainted.remove(REG_RCX); 126 | case REG_ECX: regsTainted.remove(REG_ECX); 127 | case REG_CX: regsTainted.remove(REG_CX); 128 | case REG_CH: regsTainted.remove(REG_CH); 129 | case REG_CL: regsTainted.remove(REG_CL); 130 | break; 131 | 132 | case REG_RDX: regsTainted.remove(REG_RDX); 133 | case REG_EDX: regsTainted.remove(REG_EDX); 134 | case REG_DX: regsTainted.remove(REG_DX); 135 | case REG_DH: regsTainted.remove(REG_DH); 136 | case REG_DL: regsTainted.remove(REG_DL); 137 | break; 138 | 139 | case REG_RDI: regsTainted.remove(REG_RDI); 140 | case REG_EDI: regsTainted.remove(REG_EDI); 141 | case REG_DI: regsTainted.remove(REG_DI); 142 | case REG_DIL: regsTainted.remove(REG_DIL); 143 | break; 144 | 145 | case REG_RSI: regsTainted.remove(REG_RSI); 146 | case REG_ESI: regsTainted.remove(REG_ESI); 147 | case REG_SI: regsTainted.remove(REG_SI); 148 | case REG_SIL: regsTainted.remove(REG_SIL); 149 | break; 150 | 151 | default: 152 | return false; 153 | } 154 | std::cout << "\t\t\t" << REG_StringShort(reg) << " is now freed" << std::endl; 155 | return true; 156 | } 157 | 158 | VOID ReadMem(UINT64 insAddr, std::string insDis, UINT32 opCount, REG reg_r, UINT64 memOp, UINT64 sp) 159 | { 160 | list::iterator i; 161 | UINT64 addr = memOp; 162 | 163 | if (opCount != 2) 164 | return; 165 | 166 | for(i = addressTainted.begin(); i != addressTainted.end(); i++){ 167 | if (addr == *i){ 168 | std::cout << std::hex << "[READ in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 169 | taintReg(reg_r); 170 | 171 | if (sp > addr && addr > 0x700000000000) 172 | std::cout << std::hex << "[UAF in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 173 | 174 | return ; 175 | } 176 | } 177 | /* if mem != tained and reg == taint => free the reg */ 178 | if (checkAlreadyRegTainted(reg_r)){ 179 | std::cout << std::hex << "[READ in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 180 | removeRegTainted(reg_r); 181 | } 182 | } 183 | 184 | VOID WriteMem(UINT64 insAddr, std::string insDis, UINT32 opCount, REG reg_r, UINT64 memOp, UINT64 sp) 185 | { 186 | list::iterator i; 187 | UINT64 addr = memOp; 188 | 189 | if (opCount != 2) 190 | return; 191 | 192 | for(i = addressTainted.begin(); i != addressTainted.end(); i++){ 193 | if (addr == *i){ 194 | std::cout << std::hex << "[WRITE in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 195 | if (!REG_valid(reg_r) || !checkAlreadyRegTainted(reg_r)) 196 | removeMemTainted(addr); 197 | 198 | if (sp > addr && addr > 0x700000000000) 199 | std::cout << std::hex << "[UAF in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 200 | 201 | return ; 202 | } 203 | } 204 | if (checkAlreadyRegTainted(reg_r)){ 205 | std::cout << std::hex << "[WRITE in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 206 | addMemTainted(addr); 207 | } 208 | } 209 | 210 | VOID spreadRegTaint(UINT64 insAddr, std::string insDis, UINT32 opCount, REG reg_r, REG reg_w) 211 | { 212 | if (opCount != 2) 213 | return; 214 | 215 | if (REG_valid(reg_w)){ 216 | if (checkAlreadyRegTainted(reg_w) && (!REG_valid(reg_r) || !checkAlreadyRegTainted(reg_r))){ 217 | std::cout << "[SPREAD]\t\t" << insAddr << ": " << insDis << std::endl; 218 | std::cout << "\t\t\toutput: "<< REG_StringShort(reg_w) << " | input: " << (REG_valid(reg_r) ? REG_StringShort(reg_r) : "constant") << std::endl; 219 | removeRegTainted(reg_w); 220 | } 221 | else if (!checkAlreadyRegTainted(reg_w) && checkAlreadyRegTainted(reg_r)){ 222 | std::cout << "[SPREAD]\t\t" << insAddr << ": " << insDis << std::endl; 223 | std::cout << "\t\t\toutput: " << REG_StringShort(reg_w) << " | input: "<< REG_StringShort(reg_r) << std::endl; 224 | taintReg(reg_w); 225 | } 226 | } 227 | } 228 | 229 | VOID followData(UINT64 insAddr, std::string insDis, REG reg) 230 | { 231 | if (!REG_valid(reg)) 232 | return; 233 | 234 | if (checkAlreadyRegTainted(reg)){ 235 | std::cout << "[FOLLOW]\t\t" << insAddr << ": " << insDis << std::endl; 236 | } 237 | } 238 | 239 | VOID Instruction(INS ins, VOID *v) 240 | { 241 | if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsRead(ins, 0) && INS_OperandIsReg(ins, 0)){ 242 | INS_InsertCall( 243 | ins, IPOINT_BEFORE, (AFUNPTR)ReadMem, 244 | IARG_ADDRINT, INS_Address(ins), 245 | IARG_PTR, new string(INS_Disassemble(ins)), 246 | IARG_UINT32, INS_OperandCount(ins), 247 | IARG_UINT32, INS_OperandReg(ins, 0), 248 | IARG_MEMORYOP_EA, 0, 249 | IARG_REG_VALUE, REG_STACK_PTR, 250 | IARG_END); 251 | } 252 | else if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsWritten(ins, 0)){ 253 | INS_InsertCall( 254 | ins, IPOINT_BEFORE, (AFUNPTR)WriteMem, 255 | IARG_ADDRINT, INS_Address(ins), 256 | IARG_PTR, new string(INS_Disassemble(ins)), 257 | IARG_UINT32, INS_OperandCount(ins), 258 | IARG_UINT32, INS_OperandReg(ins, 1), 259 | IARG_MEMORYOP_EA, 0, 260 | IARG_REG_VALUE, REG_STACK_PTR, 261 | IARG_END); 262 | } 263 | else if (INS_OperandCount(ins) > 1 && INS_OperandIsReg(ins, 0)){ 264 | INS_InsertCall( 265 | ins, IPOINT_BEFORE, (AFUNPTR)spreadRegTaint, 266 | IARG_ADDRINT, INS_Address(ins), 267 | IARG_PTR, new string(INS_Disassemble(ins)), 268 | IARG_UINT32, INS_OperandCount(ins), 269 | IARG_UINT32, INS_RegR(ins, 0), 270 | IARG_UINT32, INS_RegW(ins, 0), 271 | IARG_END); 272 | } 273 | 274 | if (INS_OperandCount(ins) > 1 && INS_OperandIsReg(ins, 0)){ 275 | INS_InsertCall( 276 | ins, IPOINT_BEFORE, (AFUNPTR)followData, 277 | IARG_ADDRINT, INS_Address(ins), 278 | IARG_PTR, new string(INS_Disassemble(ins)), 279 | IARG_UINT32, INS_RegR(ins, 0), 280 | IARG_END); 281 | } 282 | } 283 | 284 | static unsigned int tryksOpen; 285 | 286 | #define TRICKS(){if (tryksOpen++ == 0)return;} 287 | 288 | VOID Syscall_entry(THREADID thread_id, CONTEXT *ctx, SYSCALL_STANDARD std, void *v) 289 | { 290 | unsigned int i; 291 | UINT64 start, size; 292 | 293 | if (PIN_GetSyscallNumber(ctx, std) == __NR_read){ 294 | 295 | TRICKS(); /* tricks to ignore the first open */ 296 | 297 | start = static_cast((PIN_GetSyscallArgument(ctx, std, 1))); 298 | size = static_cast((PIN_GetSyscallArgument(ctx, std, 2))); 299 | 300 | for (i = 0; i < size; i++) 301 | addressTainted.push_back(start+i); 302 | 303 | std::cout << "[TAINT]\t\t\tbytes tainted from " << std::hex << "0x" << start << " to 0x" << start+size << " (via read)"<< std::endl; 304 | } 305 | } 306 | 307 | int main(int argc, char *argv[]) 308 | { 309 | if(PIN_Init(argc, argv)){ 310 | return Usage(); 311 | } 312 | 313 | PIN_SetSyntaxIntel(); 314 | PIN_AddSyscallEntryFunction(Syscall_entry, 0); 315 | INS_AddInstrumentFunction(Instruction, 0); 316 | PIN_StartProgram(); 317 | 318 | return 0; 319 | } 320 | 321 | -------------------------------------------------------------------------------- /ObsoleteStackFrameAccessDetection/crackme: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/ObsoleteStackFrameAccessDetection/crackme -------------------------------------------------------------------------------- /ObsoleteStackFrameAccessDetection/crackme.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Jonathan Salwan - Copyright (C) 2013-07 3 | ** 4 | ** http://twitter.com/JonathanSalwan 5 | ** http://shell-storm.org 6 | ** 7 | ** This program is free software: you can redistribute it and/or modify 8 | ** it under the terms of the GNU General Public License as published by 9 | ** the Free Software Foundation, either version 3 of the License, or 10 | ** (at your option) any later version. 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | char *serial = "\x30\x39\x3c\x21\x30"; 19 | 20 | int main(void) 21 | { 22 | int fd, i = 0; 23 | char *buf; 24 | char *r; 25 | 26 | buf = malloc(256); 27 | if (!buf) 28 | return -1; 29 | r = buf; 30 | fd = open("serial.txt", O_RDONLY); 31 | read(fd, buf, 256); 32 | close(fd); 33 | while (i < 5){ 34 | if ((*buf ^ 0x55) != *serial) 35 | return 0; 36 | buf++, serial++, i++; 37 | } 38 | if (!*buf) 39 | printf("Good boy\n"); 40 | free(r); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /ObsoleteStackFrameAccessDetection/file.txt: -------------------------------------------------------------------------------- 1 | ABCD 2 | -------------------------------------------------------------------------------- /ObsoleteStackFrameAccessDetection/makefile: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # DO NOT EDIT THIS FILE! 4 | # 5 | ############################################################## 6 | 7 | # If the tool is built out of the kit, PIN_ROOT must be specified in the make invocation and point to the kit root. 8 | ifdef PIN_ROOT 9 | CONFIG_ROOT := $(PIN_ROOT)/source/tools/Config 10 | else 11 | CONFIG_ROOT := ../Config 12 | endif 13 | include $(CONFIG_ROOT)/makefile.config 14 | include makefile.rules 15 | include $(TOOLS_ROOT)/Config/makefile.default.rules 16 | 17 | ############################################################## 18 | # 19 | # DO NOT EDIT THIS FILE! 20 | # 21 | ############################################################## 22 | -------------------------------------------------------------------------------- /ObsoleteStackFrameAccessDetection/makefile.rules: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # This file includes all the test targets as well as all the 4 | # non-default build rules and test recipes. 5 | # 6 | ############################################################## 7 | 8 | 9 | ############################################################## 10 | # 11 | # Test targets 12 | # 13 | ############################################################## 14 | 15 | ###### Place all generic definitions here ###### 16 | 17 | # This defines tests which run tools of the same name. This is simply for convenience to avoid 18 | # defining the test name twice (once in TOOL_ROOTS and again in TEST_ROOTS). 19 | # Tests defined here should not be defined in TOOL_ROOTS and TEST_ROOTS. 20 | TEST_TOOL_ROOTS := Taint 21 | 22 | # This defines the tests to be run that were not already defined in TEST_TOOL_ROOTS. 23 | TEST_ROOTS := 24 | 25 | # This defines a list of tests that should run in the "short" sanity. Tests in this list must also 26 | # appear either in the TEST_TOOL_ROOTS or the TEST_ROOTS list. 27 | # If the entire directory should be tested in sanity, assign TEST_TOOL_ROOTS and TEST_ROOTS to the 28 | # SANITY_SUBSET variable in the tests section below (see example in makefile.rules.tmpl). 29 | SANITY_SUBSET := 30 | 31 | # This defines the tools which will be run during the the tests, and were not already defined in 32 | # TEST_TOOL_ROOTS. 33 | TOOL_ROOTS := 34 | 35 | # This defines the static analysis tools which will be run during the the tests. They should not 36 | # be defined in TEST_TOOL_ROOTS. If a test with the same name exists, it should be defined in 37 | # TEST_ROOTS. 38 | # Note: Static analysis tools are in fact executables linked with the Pin Static Analysis Library. 39 | # This library provides a subset of the Pin APIs which allows the tool to perform static analysis 40 | # of an application or dll. Pin itself is not used when this tool runs. 41 | SA_TOOL_ROOTS := 42 | 43 | # This defines all the applications that will be run during the tests. 44 | APP_ROOTS := 45 | 46 | # This defines any additional object files that need to be compiled. 47 | OBJECT_ROOTS := 48 | 49 | # This defines any additional dlls (shared objects), other than the pintools, that need to be compiled. 50 | DLL_ROOTS := 51 | 52 | # This defines any static libraries (archives), that need to be built. 53 | LIB_ROOTS := 54 | 55 | 56 | ############################################################## 57 | # 58 | # Test recipes 59 | # 60 | ############################################################## 61 | 62 | # This section contains recipes for tests other than the default. 63 | # See makefile.default.rules for the default test rules. 64 | # All tests in this section should adhere to the naming convention: .test 65 | 66 | 67 | ############################################################## 68 | # 69 | # Build rules 70 | # 71 | ############################################################## 72 | 73 | # This section contains the build rules for all binaries that have special build rules. 74 | # See makefile.default.rules for the default build rules. 75 | -------------------------------------------------------------------------------- /ObsoleteStackFrameAccessDetection/pin.log: -------------------------------------------------------------------------------- 1 | Pin 2.12 kit 58423 2 | E: Missing application name 3 | -------------------------------------------------------------------------------- /ObsoleteStackFrameAccessDetection/pintool.log: -------------------------------------------------------------------------------- 1 | Pin 2.12 kit 58423 2 | A: Source/pin/core_ia32/operand_ia32.cpp:INS_OperandIsReg:INS_OperandIsReg:356: assertion failed: n < xed_inst_noperands(xedi) 3 | 4 | -------------------------------------------------------------------------------- /ObsoleteStackFrameAccessDetection/test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/ObsoleteStackFrameAccessDetection/test -------------------------------------------------------------------------------- /ObsoleteStackFrameAccessDetection/test.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define true 0 9 | #define false !true 10 | 11 | char *foo2(char *buf) 12 | { 13 | char d = buf[0]; 14 | return &d; 15 | } 16 | 17 | int foo1(char *buf) 18 | { 19 | *foo2(buf) = 1; /* UAF match */ 20 | } 21 | 22 | int main(int ac, char **av) 23 | { 24 | int fd; 25 | char *buf; 26 | 27 | if (!(buf = malloc(32))) 28 | return -1; 29 | 30 | fd = open("./file.txt", O_RDONLY); 31 | read(fd, buf, 32), close(fd); 32 | foo1(buf); 33 | } 34 | -------------------------------------------------------------------------------- /OverflowDetection/OverflowDetection.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Jonathan Salwan - Copyright (C) 2013-09 3 | // 4 | // http://shell-storm.org 5 | // http://twitter.com/JonathanSalwan 6 | // 7 | // 8 | 9 | #include "pin.H" 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define LOCKED 1 16 | #define UNLOCKED !LOCKED 17 | 18 | #define ALLOCATE 1 19 | #define FREE !ALLOCATE 20 | 21 | #define DEBUG 22 | 23 | #define NextIT(_x) ((++_x)--) 24 | 25 | static size_t lastSize; 26 | static size_t timerJiffies; 27 | 28 | static UINT16 _tabAddr[0x10000]; 29 | static std::string _tabStr[0x10000]; 30 | 31 | struct mallocArea 32 | { 33 | UINT64 base; 34 | UINT64 size; 35 | BOOL status; 36 | }; 37 | 38 | struct loopList_s 39 | { 40 | UINT32 idLoop; 41 | std::list addrs; 42 | }; 43 | 44 | static UINT64 stID = 0; 45 | 46 | struct stackFrameVar_s 47 | { 48 | UINT64 addrVar; 49 | UINT64 sizeVar; 50 | UINT64 rsp; 51 | }; 52 | 53 | struct VSA 54 | { 55 | std::list stackFrameVar; 56 | }; 57 | 58 | struct VSA VSAL[64]; 59 | 60 | UINT32 lockTaint = LOCKED; 61 | 62 | std::list addressTainted; 63 | std::list regsTainted; 64 | std::list mallocAreaList; 65 | 66 | INT32 Usage() 67 | { 68 | std::cerr << "Stack/Heap overflow detection" << std::endl; 69 | return -1; 70 | } 71 | 72 | VOID WriteMem(UINT64 insAddr, std::string insDis, UINT32 opCount, REG reg_r, UINT64 memOp) 73 | { 74 | std::list::iterator i; 75 | UINT64 addr = memOp; 76 | PIN_LockClient(); 77 | IMG img = IMG_FindByAddress(addr); 78 | PIN_UnlockClient(); 79 | SEC sec; 80 | 81 | if (opCount != 2){ 82 | return; 83 | } 84 | 85 | /* Check if the address is in a section */ 86 | for(sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)){ 87 | if (addr >= SEC_Address(sec) && addr < (SEC_Address(sec) + SEC_Size(sec))) 88 | return; 89 | } 90 | 91 | /* Check if the address is mapped */ 92 | for(i = mallocAreaList.begin(); i != mallocAreaList.end(); i++){ 93 | if (i->status == ALLOCATE && addr >= i->base && addr < (i->base + i->size)) 94 | return; 95 | if (i->status == FREE && addr >= i->base && addr < (i->base + i->size)){ 96 | std::cout << std::hex << insAddr << ": " << insDis << " -- Use after free in " << addr << std::endl; 97 | return; 98 | } 99 | } 100 | 101 | /* check if the address is in a stack area */ 102 | if (addr > 0x700000000000) 103 | return; 104 | 105 | std::cout << std::hex << insAddr << ": " << insDis << " -- Heap overflow in " << addr << std::endl; 106 | } 107 | 108 | VOID PrologueAnalysis(UINT64 insAddr, UINT64 nextInsAddr, std::string insDis) 109 | { 110 | UINT64 i = 0; 111 | list::iterator it; 112 | 113 | if (nextInsAddr >= 0x4004a0){ 114 | #ifdef DEBUG 115 | //std::cout << "Function opened " << hex << nextInsAddr << std::endl; 116 | #endif 117 | 118 | if (VSAL[stID].stackFrameVar.size() == 0){ 119 | stID++; 120 | return; 121 | } 122 | 123 | /* premiere passe */ 124 | for(it = VSAL[stID].stackFrameVar.begin(); it != VSAL[stID].stackFrameVar.end(); it++){ 125 | if (i++ != 0){ 126 | it->sizeVar = it->addrVar - (--it)->addrVar; 127 | it++; 128 | } 129 | } 130 | 131 | /* deuxieme passe */ 132 | for(it = VSAL[stID].stackFrameVar.begin(); it != VSAL[stID].stackFrameVar.end(); it++){ 133 | if (it->sizeVar == 0 && it->rsp < it->addrVar){ 134 | it->sizeVar = it->addrVar - it->rsp; 135 | } 136 | } 137 | 138 | stID++; 139 | } 140 | } 141 | 142 | VOID EpilogueAnalysis(UINT64 insAddr, UINT64 nextInsAddr, std::string insDis) 143 | { 144 | if (nextInsAddr >= 0x4004a0){ 145 | #ifdef DEBUG 146 | //std::cout << "Function closed" << std::endl; 147 | #endif 148 | } 149 | } 150 | 151 | VOID ValueSetAnalysis(UINT64 insAddr, std::string insDis, ADDRINT rsp, ADDRINT rbp, UINT64 memOp) 152 | { 153 | UINT64 addrRBP = memOp; 154 | struct stackFrameVar_s elem; 155 | list::iterator i; 156 | 157 | #ifdef DEBUG 158 | std::cout << insAddr << ": " << insDis << " (rsp: " << std::hex << rsp << ") (rbp: " << rbp << ") (dest: " << addrRBP << ") (stack frame ID: " << std::dec << stID << ")" << std::endl; 159 | #endif 160 | 161 | /* Ajout des variables de la stack frame dans une VSAL */ 162 | /* stID est unique pour chaque stack frame */ 163 | elem.addrVar = addrRBP; 164 | elem.sizeVar = 0; 165 | elem.rsp = rsp; 166 | /* boucle pour eviter les doublons et eviter d'avoir plusieur */ 167 | /* variables pour une meme initialisation */ 168 | for(i = VSAL[stID].stackFrameVar.begin(); i != VSAL[stID].stackFrameVar.end(); i++){ 169 | if (i->addrVar == addrRBP) 170 | return; 171 | } 172 | 173 | if (VSAL[stID].stackFrameVar.size() == 0){ 174 | VSAL[stID].stackFrameVar.push_back(elem); 175 | return; 176 | } 177 | 178 | for(i = VSAL[stID].stackFrameVar.begin(); i != VSAL[stID].stackFrameVar.end(); i++){ 179 | if (i->addrVar > addrRBP){ 180 | VSAL[stID].stackFrameVar.push_front(elem); 181 | return; 182 | } 183 | } 184 | VSAL[stID].stackFrameVar.push_back(elem); 185 | } 186 | 187 | VOID timerHandler(UINT64 prevAddr, UINT64 insAddr, UINT64 nextAddr, std::string insDis) 188 | { 189 | timerJiffies++; 190 | 191 | 192 | if (insAddr > 0x700000000000) 193 | return; 194 | 195 | if (_tabAddr[insAddr ^ 0x400000] == 0xffff) 196 | return; 197 | 198 | _tabAddr[insAddr ^ 0x400000] += 1; 199 | _tabStr[insAddr ^ 0x400000] = insDis; 200 | } 201 | 202 | static UINT64 oldAddrWritten = 0; 203 | static UINT64 counterWrite = 0; 204 | static UINT64 oldRIP = 0; 205 | 206 | VOID WriteMemAnalysis(UINT64 insAddr, std::string insDis, UINT64 memOp) 207 | { 208 | list::iterator it; 209 | list::iterator itNext; 210 | UINT64 addr = memOp; 211 | 212 | 213 | // if (_tabAddr[insAddr ^ 0x400000] < 2) 214 | // return; 215 | 216 | for(it = VSAL[stID].stackFrameVar.begin(); it != VSAL[stID].stackFrameVar.end(); it++){ 217 | //std::cout << "addr = " << std::hex << addr << std::endl; 218 | //std::cout << "addrVar = " << std::hex << it->addrVar << std::endl; 219 | //std::cout << "addrSize = " << std::hex << it->sizeVar << std::endl; 220 | 221 | itNext = NextIT(it); 222 | if (addr >= it->addrVar && addr < itNext->addrVar){ 223 | #ifdef DEBUG 224 | std::cout << "[Write Mem B] " << std::hex << insAddr << ": " << insDis << std::endl; 225 | #endif 226 | 227 | if (oldAddrWritten == 0) 228 | oldAddrWritten = addr; 229 | 230 | 231 | if (((addr - oldAddrWritten) != 1 && oldAddrWritten != addr) || insAddr != oldRIP){ 232 | counterWrite = 0; 233 | oldAddrWritten = addr; 234 | } 235 | 236 | counterWrite++; 237 | oldRIP = insAddr; 238 | 239 | if (counterWrite > 4){ 240 | std::cout << std::hex << insAddr << ": " << insDis << " -- Stack overflow in " << addr << std::endl; 241 | counterWrite = 0; 242 | oldAddrWritten = addr; 243 | } 244 | 245 | #ifdef DEBUG 246 | std::cout << "counterWrite: " << std::dec << counterWrite << std::endl; 247 | #endif 248 | oldAddrWritten = addr; 249 | break; 250 | } 251 | // std::cout << "itNext: " << std::hex << itNext->addrVar << std::endl; 252 | } 253 | } 254 | 255 | VOID Instruction(INS ins, VOID *v) 256 | { 257 | PIN_LockClient(); 258 | IMG img = IMG_FindByAddress(INS_Address(ins)); 259 | PIN_UnlockClient(); 260 | 261 | if (IMG_Valid(img) && IMG_IsMainExecutable(img)){ 262 | if (INS_IsCall(ins)){ 263 | INS_InsertCall( 264 | ins, IPOINT_BEFORE, (AFUNPTR)PrologueAnalysis, 265 | IARG_ADDRINT, INS_Address(ins), 266 | IARG_ADDRINT, INS_NextAddress(ins), 267 | IARG_PTR, new string(INS_Disassemble(ins)), 268 | IARG_END); 269 | } 270 | else if (INS_IsRet(ins)){ 271 | INS_InsertCall( 272 | ins, IPOINT_BEFORE, (AFUNPTR)EpilogueAnalysis, 273 | IARG_ADDRINT, INS_Address(ins), 274 | IARG_ADDRINT, INS_NextAddress(ins), 275 | IARG_PTR, new string(INS_Disassemble(ins)), 276 | IARG_END); 277 | } 278 | else if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsWritten(ins, 0)){ 279 | INS_InsertCall( 280 | ins, IPOINT_BEFORE, (AFUNPTR)WriteMem, 281 | IARG_ADDRINT, INS_Address(ins), 282 | IARG_PTR, new string(INS_Disassemble(ins)), 283 | IARG_UINT32, INS_OperandCount(ins), 284 | IARG_UINT32, INS_OperandReg(ins, 1), 285 | IARG_MEMORYOP_EA, 0, 286 | IARG_END); 287 | } 288 | 289 | /* Value Set Analysis */ 290 | if (INS_Opcode(ins) == XED_ICLASS_MOV && 291 | INS_RegR(ins, 0) == REG_RBP && 292 | INS_RegR(ins, 1) == REG_INVALID() && 293 | INS_IsMemoryWrite(ins)){ 294 | INS_InsertCall( 295 | ins, IPOINT_BEFORE, (AFUNPTR)ValueSetAnalysis, 296 | IARG_ADDRINT, INS_Address(ins), 297 | IARG_PTR, new string(INS_Disassemble(ins)), 298 | IARG_REG_VALUE, REG_RSP, 299 | IARG_REG_VALUE, REG_RBP, 300 | IARG_MEMORYOP_EA, 0, 301 | IARG_END); 302 | } 303 | 304 | /* Analyzes stack overflow */ 305 | if (INS_MemoryOperandIsWritten(ins, 0)){ 306 | INS_InsertCall( 307 | ins, IPOINT_BEFORE, (AFUNPTR)WriteMemAnalysis, 308 | IARG_ADDRINT, INS_Address(ins), 309 | IARG_PTR, new string(INS_Disassemble(ins)), 310 | IARG_MEMORYOP_EA, 0, 311 | IARG_END); 312 | } 313 | 314 | /* Timer Handler - And instruction counter */ 315 | INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)timerHandler, 316 | IARG_ADDRINT, INS_Address(INS_Prev(ins)), 317 | IARG_ADDRINT, INS_Address(ins), 318 | IARG_ADDRINT, INS_Address(INS_Next(ins)), 319 | IARG_PTR, new string(INS_Disassemble(ins)), 320 | IARG_END); 321 | 322 | } 323 | } 324 | 325 | VOID callbackBeforeMalloc(ADDRINT size) 326 | { 327 | lastSize = size; 328 | } 329 | 330 | VOID callbackBeforeFree(ADDRINT addr) 331 | { 332 | list::iterator i; 333 | 334 | #ifdef DEBUG 335 | std::cout << "[INFO] free(" << std::hex << addr << ")" << std::endl; 336 | #endif 337 | for(i = mallocAreaList.begin(); i != mallocAreaList.end(); i++){ 338 | if (addr == i->base){ 339 | i->status = FREE; 340 | break; 341 | } 342 | } 343 | } 344 | 345 | VOID callbackAfterMalloc(ADDRINT ret) 346 | { 347 | list::iterator i; 348 | struct mallocArea elem; 349 | 350 | #ifdef DEBUG 351 | std::cout << "[INFO] malloc(" << std::dec << lastSize << ") = " << std::hex << ret << std::endl; 352 | #endif 353 | if (ret){ 354 | 355 | for(i = mallocAreaList.begin(); i != mallocAreaList.end(); i++){ 356 | if (ret == i->base){ 357 | i->status = ALLOCATE; 358 | i->size = lastSize; 359 | return; 360 | } 361 | } 362 | elem.base = ret; 363 | elem.size = lastSize; 364 | elem.status = ALLOCATE; 365 | mallocAreaList.push_front(elem); 366 | } 367 | } 368 | 369 | VOID Image(IMG img, VOID *v) 370 | { 371 | RTN mallocRtn = RTN_FindByName(img, "malloc"); 372 | RTN freeRtn = RTN_FindByName(img, "free"); 373 | 374 | if (RTN_Valid(mallocRtn)){ 375 | RTN_Open(mallocRtn); 376 | 377 | RTN_InsertCall( 378 | mallocRtn, 379 | IPOINT_BEFORE, (AFUNPTR)callbackBeforeMalloc, 380 | IARG_FUNCARG_ENTRYPOINT_VALUE, 0, 381 | IARG_END); 382 | 383 | RTN_InsertCall( 384 | mallocRtn, 385 | IPOINT_AFTER, (AFUNPTR)callbackAfterMalloc, 386 | IARG_FUNCRET_EXITPOINT_VALUE, 387 | IARG_END); 388 | 389 | RTN_Close(mallocRtn); 390 | } 391 | 392 | if (RTN_Valid(freeRtn)){ 393 | RTN_Open(freeRtn); 394 | RTN_InsertCall( 395 | freeRtn, 396 | IPOINT_BEFORE, (AFUNPTR)callbackBeforeFree, 397 | IARG_FUNCARG_ENTRYPOINT_VALUE, 0, 398 | IARG_END); 399 | RTN_Close(freeRtn); 400 | } 401 | } 402 | 403 | #ifdef DEBUG 404 | VOID Fini(INT32 code, VOID *v) 405 | { 406 | UINT32 i; 407 | list::iterator it; 408 | 409 | for (i = 0; i < 32; i++){ 410 | if (VSAL[i].stackFrameVar.size()){ 411 | std::cout << "id stack frame: " << std::dec << i << "\t Num var: " << VSAL[i].stackFrameVar.size() << " ( "; 412 | 413 | for(it = VSAL[i].stackFrameVar.begin(); it != VSAL[i].stackFrameVar.end(); it++){ 414 | std::cout << std::hex << it->addrVar << ":" << std::dec << it->sizeVar << " "; 415 | } 416 | std::cout << ")" << std::endl; 417 | } 418 | } 419 | 420 | std::cout << "------------------" << std::endl; 421 | std::cout << "Addr\tNumber\tDisass" << std::endl; 422 | for (i = 0; i < 0x10000; i++){ 423 | if (_tabAddr[i]) 424 | std::cout << std::hex << (0x400000 + i) << "\t" << std::dec << _tabAddr[i] << "\t" << _tabStr[i] << std::endl; 425 | } 426 | } 427 | #endif 428 | 429 | int main(int argc, char *argv[]) 430 | { 431 | PIN_InitSymbols(); 432 | if(PIN_Init(argc, argv)){ 433 | return Usage(); 434 | } 435 | 436 | PIN_SetSyntaxIntel(); 437 | IMG_AddInstrumentFunction(Image, 0); 438 | INS_AddInstrumentFunction(Instruction, 0); 439 | #ifdef DEBUG 440 | PIN_AddFiniFunction(Fini, 0); 441 | #endif 442 | PIN_StartProgram(); 443 | 444 | return 0; 445 | } 446 | 447 | -------------------------------------------------------------------------------- /OverflowDetection/makefile: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # DO NOT EDIT THIS FILE! 4 | # 5 | ############################################################## 6 | 7 | # If the tool is built out of the kit, PIN_ROOT must be specified in the make invocation and point to the kit root. 8 | ifdef PIN_ROOT 9 | CONFIG_ROOT := $(PIN_ROOT)/source/tools/Config 10 | else 11 | CONFIG_ROOT := ../Config 12 | endif 13 | include $(CONFIG_ROOT)/makefile.config 14 | include makefile.rules 15 | include $(TOOLS_ROOT)/Config/makefile.default.rules 16 | 17 | TOOL_INCLUDES += ./src/api/c++/ 18 | 19 | ############################################################## 20 | # 21 | # DO NOT EDIT THIS FILE! 22 | # 23 | ############################################################## 24 | -------------------------------------------------------------------------------- /OverflowDetection/makefile.rules: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # This file includes all the test targets as well as all the 4 | # non-default build rules and test recipes. 5 | # 6 | ############################################################## 7 | 8 | 9 | ############################################################## 10 | # 11 | # Test targets 12 | # 13 | ############################################################## 14 | 15 | ###### Place all generic definitions here ###### 16 | 17 | # This defines tests which run tools of the same name. This is simply for convenience to avoid 18 | # defining the test name twice (once in TOOL_ROOTS and again in TEST_ROOTS). 19 | # Tests defined here should not be defined in TOOL_ROOTS and TEST_ROOTS. 20 | TEST_TOOL_ROOTS := OverflowDetection 21 | 22 | # This defines the tests to be run that were not already defined in TEST_TOOL_ROOTS. 23 | TEST_ROOTS := 24 | 25 | # This defines a list of tests that should run in the "short" sanity. Tests in this list must also 26 | # appear either in the TEST_TOOL_ROOTS or the TEST_ROOTS list. 27 | # If the entire directory should be tested in sanity, assign TEST_TOOL_ROOTS and TEST_ROOTS to the 28 | # SANITY_SUBSET variable in the tests section below (see example in makefile.rules.tmpl). 29 | SANITY_SUBSET := 30 | 31 | # This defines the tools which will be run during the the tests, and were not already defined in 32 | # TEST_TOOL_ROOTS. 33 | TOOL_ROOTS := 34 | 35 | # This defines the static analysis tools which will be run during the the tests. They should not 36 | # be defined in TEST_TOOL_ROOTS. If a test with the same name exists, it should be defined in 37 | # TEST_ROOTS. 38 | # Note: Static analysis tools are in fact executables linked with the Pin Static Analysis Library. 39 | # This library provides a subset of the Pin APIs which allows the tool to perform static analysis 40 | # of an application or dll. Pin itself is not used when this tool runs. 41 | SA_TOOL_ROOTS := 42 | 43 | # This defines all the applications that will be run during the tests. 44 | APP_ROOTS := 45 | 46 | # This defines any additional object files that need to be compiled. 47 | OBJECT_ROOTS := 48 | 49 | # This defines any additional dlls (shared objects), other than the pintools, that need to be compiled. 50 | DLL_ROOTS := 51 | 52 | # This defines any static libraries (archives), that need to be built. 53 | LIB_ROOTS := z3/build/libz3.so 54 | 55 | 56 | ############################################################## 57 | # 58 | # Test recipes 59 | # 60 | ############################################################## 61 | 62 | # This section contains recipes for tests other than the default. 63 | # See makefile.default.rules for the default test rules. 64 | # All tests in this section should adhere to the naming convention: .test 65 | 66 | 67 | ############################################################## 68 | # 69 | # Build rules 70 | # 71 | ############################################################## 72 | 73 | # This section contains the build rules for all binaries that have special build rules. 74 | # See makefile.default.rules for the default build rules. 75 | -------------------------------------------------------------------------------- /OverflowDetection/test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/OverflowDetection/test -------------------------------------------------------------------------------- /OverflowDetection/test.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Jonathan Salwan - 2013-09-04 3 | ** 4 | ** http://shell-storm.org 5 | ** http://twitter.com/JonathanSalwan 6 | ** 7 | ** This program is free software: you can redistribute it and/or modify 8 | ** it under the terms of the GNU General Public License as published by 9 | ** the Free Software Foundation, either version 3 of the License, or 10 | ** (at your option) any later version. 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #define BUFF_MAX 32 18 | 19 | void test4_heap_overflow(char *buff1) 20 | { 21 | /* 5 bytes overwritten outside the area "42 42 42 42 00" */ 22 | strcpy(buff1, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB"); 23 | } 24 | 25 | void test5_stack_overflow(void) 26 | { 27 | int a, b, i; 28 | 29 | a = 0x90909090; 30 | b = 0x91919191; 31 | 32 | for (i = 0; i <= sizeof(b); i++) 33 | *(((unsigned char *)(&b))+i) = 'E'; 34 | 35 | } 36 | 37 | int main(int ac, const char *av[]) 38 | { 39 | char *buff1 = NULL, *buff2 = NULL; 40 | int i = 0; 41 | 42 | buff1 = malloc(BUFF_MAX); 43 | buff2 = malloc(BUFF_MAX); 44 | if (!buff1 || !buff2) 45 | return -1; 46 | 47 | /* Test 1 - heap overflow (off-by-one) */ 48 | for (i = 0; i <= BUFF_MAX; i++) 49 | buff1[i] = 'A'; 50 | 51 | /* Test 2 - heap overflow (off-by-one) - Via linear buffer buff1->buff2 */ 52 | for (i = 0; i <= BUFF_MAX; i++) 53 | buff2[i] = 'B'; 54 | 55 | /* Test 3 - Use after free */ 56 | free(buff1); 57 | buff1[16] = 'C'; /* Will match */ 58 | buff1 = malloc(BUFF_MAX); 59 | buff1[16] = 'C'; /* Will not match */ 60 | 61 | /* Test 4 - Classical Heap overflow */ 62 | test4_heap_overflow(buff1); 63 | 64 | /* Test 5 - Stack overclow */ 65 | test5_stack_overflow(); 66 | 67 | return 0; 68 | } 69 | 70 | -------------------------------------------------------------------------------- /OverflowDetection/test1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/OverflowDetection/test1 -------------------------------------------------------------------------------- /OverflowDetection/test1.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Jonathan Salwan - 2013-10-12 3 | ** 4 | ** http://shell-storm.org 5 | ** http://twitter.com/JonathanSalwan 6 | ** 7 | ** This program is free software: you can redistribute it and/or modify 8 | ** it under the terms of the GNU General Public License as published by 9 | ** the Free Software Foundation, either version 3 of the License, or 10 | ** (at your option) any later version. 11 | */ 12 | 13 | void foo(void) 14 | { 15 | int a, b, i; 16 | 17 | a = 0x90909090; 18 | b = 0x91919191; 19 | 20 | for (i = 0; i <= sizeof(b); i++) /* off-by-one */ 21 | *(((unsigned char *)(&b))+i) = 'E'; 22 | 23 | } 24 | 25 | int main(int ac, const char *av[]) 26 | { 27 | foo(); 28 | } 29 | -------------------------------------------------------------------------------- /OverflowDetection/testcpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/OverflowDetection/testcpp -------------------------------------------------------------------------------- /OverflowDetection/testcpp.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Jonathan Salwan - 2013-09-09 3 | // 4 | // http://shell-storm.org 5 | // http://twitter.com/JonathanSalwan 6 | // 7 | // This program is free software: you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation, either version 3 of the License, or 10 | // (at your option) any later version. 11 | // 12 | 13 | #include 14 | 15 | #define CONST_SIZE 32 16 | 17 | class Test 18 | { 19 | private: 20 | char *_buffer; 21 | 22 | 23 | public: 24 | 25 | Test(){ 26 | this->_buffer = new char[CONST_SIZE]; 27 | }; 28 | 29 | ~Test(){ 30 | delete [] this->_buffer; 31 | }; 32 | 33 | void fillBuffer(void){ 34 | unsigned int i; 35 | 36 | for (i = 0; i <= CONST_SIZE; i++) /* off-by-one */ 37 | this->_buffer[i] = 'A'; 38 | }; 39 | }; 40 | 41 | int main(int ac, const char *av[]) 42 | { 43 | Test test; 44 | 45 | test.fillBuffer(); 46 | 47 | return 0; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /PointerWithoutCheckDetection/Taint.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Jonathan Salwan - Copyright (C) 2013-08 3 | // 4 | // http://shell-storm.org 5 | // http://twitter.com/JonathanSalwan 6 | // 7 | // Note: Example 6 - http://shell-storm.org/blog/Taint-analysis-with-Pin/ 8 | // Detect pointer utilization without check 9 | // 10 | 11 | #include "pin.H" 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define LOCKED 1 18 | #define UNLOCKED !LOCKED 19 | 20 | #define ALLOCATE 1 21 | #define FREE !ALLOCATE 22 | 23 | #define CHECKED 1 24 | 25 | static size_t lastSize; 26 | 27 | struct mallocArea 28 | { 29 | UINT64 base; 30 | UINT64 size; 31 | BOOL status; 32 | BOOL check; 33 | }; 34 | 35 | UINT32 lockTaint = LOCKED; 36 | 37 | std::list addressTainted; 38 | std::list regsTainted; 39 | std::list mallocAreaList; 40 | 41 | INT32 Usage() 42 | { 43 | std::cerr << "Ex 6" << std::endl; 44 | return -1; 45 | } 46 | 47 | VOID ReadMem(UINT64 insAddr, std::string insDis, UINT64 memOp) 48 | { 49 | list::iterator i; 50 | UINT64 addr = memOp; 51 | 52 | for(i = mallocAreaList.begin(); i != mallocAreaList.end(); i++){ 53 | if (i->base == addr && i->check != CHECKED) 54 | std::cout << std::hex << "[READ in " << addr << " without check]\t\t" << insAddr << ": " << insDis << std::endl; 55 | } 56 | } 57 | 58 | VOID WriteMem(UINT64 insAddr, std::string insDis, UINT64 memOp) 59 | { 60 | list::iterator i; 61 | UINT64 addr = memOp; 62 | 63 | for(i = mallocAreaList.begin(); i != mallocAreaList.end(); i++){ 64 | if (i->base == addr && i->check != CHECKED) 65 | std::cout << std::hex << "[WRITE in " << addr << " without check]\t\t" << insAddr << ": " << insDis << std::endl; 66 | } 67 | } 68 | 69 | VOID cmpInst(UINT64 insAddr, std::string insDis, UINT64 memOp) 70 | { 71 | list::iterator i; 72 | UINT64 addr = memOp; 73 | 74 | for(i = mallocAreaList.begin(); i != mallocAreaList.end(); i++){ 75 | if (*(UINT64 *)addr == i->base){ 76 | //std::cout << std::hex << "[PTR " << *(UINT64 *)addr << " checked]\t\t\t" << insAddr << ": " << insDis << std::endl; 77 | i->check = CHECKED; 78 | } 79 | } 80 | } 81 | 82 | VOID testInst(UINT64 insAddr, std::string insDis, ADDRINT val_r0, ADDRINT val_r1) 83 | { 84 | list::iterator i; 85 | 86 | for(i = mallocAreaList.begin(); i != mallocAreaList.end(); i++){ 87 | if (val_r0 == val_r1 && val_r0 == i->base){ 88 | //std::cout << std::hex << "[PTR " << val_r0 << " checked]\t\t\t" << insAddr << ": " << insDis << std::endl; 89 | i->check = CHECKED; 90 | } 91 | } 92 | } 93 | 94 | VOID Instruction(INS ins, VOID *v) 95 | { 96 | if (INS_MemoryOperandIsRead(ins, 0) && INS_OperandIsReg(ins, 0)){ 97 | INS_InsertCall( 98 | ins, IPOINT_BEFORE, (AFUNPTR)ReadMem, 99 | IARG_ADDRINT, INS_Address(ins), 100 | IARG_PTR, new string(INS_Disassemble(ins)), 101 | IARG_MEMORYOP_EA, 0, 102 | IARG_END); 103 | } 104 | else if (INS_MemoryOperandIsWritten(ins, 0)){ 105 | INS_InsertCall( 106 | ins, IPOINT_BEFORE, (AFUNPTR)WriteMem, 107 | IARG_ADDRINT, INS_Address(ins), 108 | IARG_PTR, new string(INS_Disassemble(ins)), 109 | IARG_MEMORYOP_EA, 0, 110 | IARG_END); 111 | } 112 | else if (INS_Opcode(ins) == XED_ICLASS_CMP && INS_OperandIsMemory(ins, 0)){ 113 | INS_InsertCall( 114 | ins, IPOINT_BEFORE, (AFUNPTR)cmpInst, 115 | IARG_ADDRINT, INS_Address(ins), 116 | IARG_PTR, new string(INS_Disassemble(ins)), 117 | IARG_MEMORYOP_EA, 0, 118 | IARG_END); 119 | } 120 | else if (INS_Opcode(ins) == XED_ICLASS_TEST && INS_OperandCount(ins) >= 2 && 121 | REG_valid(INS_OperandReg(ins, 0)) && REG_valid(INS_OperandReg(ins, 1))){ 122 | INS_InsertCall( 123 | ins, IPOINT_BEFORE, (AFUNPTR)testInst, 124 | IARG_ADDRINT, INS_Address(ins), 125 | IARG_PTR, new string(INS_Disassemble(ins)), 126 | IARG_REG_VALUE, INS_OperandReg(ins, 0), 127 | IARG_REG_VALUE, INS_OperandReg(ins, 1), 128 | IARG_END); 129 | } 130 | } 131 | 132 | VOID callbackBeforeMalloc(ADDRINT size) 133 | { 134 | lastSize = size; 135 | } 136 | 137 | VOID callbackBeforeFree(ADDRINT addr) 138 | { 139 | list::iterator i; 140 | 141 | //std::cout << "[INFO]\t\t\t\t\tfree(" << std::hex << addr << ")" << std::endl; 142 | for(i = mallocAreaList.begin(); i != mallocAreaList.end(); i++){ 143 | if (addr == i->base){ 144 | i->status = FREE; 145 | break; 146 | } 147 | } 148 | } 149 | 150 | VOID callbackAfterMalloc(ADDRINT ret) 151 | { 152 | list::iterator i; 153 | struct mallocArea elem; 154 | 155 | //std::cout << "[INFO]\t\t\t\t\tmalloc(" << lastSize << ") = " << std::hex << ret << std::endl; 156 | if (ret){ 157 | 158 | for(i = mallocAreaList.begin(); i != mallocAreaList.end(); i++){ 159 | if (ret == i->base){ 160 | i->status = ALLOCATE; 161 | i->size = lastSize; 162 | i->check = !CHECKED; 163 | return; 164 | } 165 | } 166 | elem.base = ret; 167 | elem.size = lastSize; 168 | elem.status = ALLOCATE; 169 | elem.check = !CHECKED; 170 | mallocAreaList.push_front(elem); 171 | } 172 | } 173 | 174 | VOID Image(IMG img, VOID *v) 175 | { 176 | RTN mallocRtn = RTN_FindByName(img, "malloc"); 177 | RTN freeRtn = RTN_FindByName(img, "free"); 178 | 179 | if (RTN_Valid(mallocRtn)){ 180 | RTN_Open(mallocRtn); 181 | 182 | RTN_InsertCall( 183 | mallocRtn, 184 | IPOINT_BEFORE, (AFUNPTR)callbackBeforeMalloc, 185 | IARG_FUNCARG_ENTRYPOINT_VALUE, 0, 186 | IARG_END); 187 | 188 | RTN_InsertCall( 189 | mallocRtn, 190 | IPOINT_AFTER, (AFUNPTR)callbackAfterMalloc, 191 | IARG_FUNCRET_EXITPOINT_VALUE, 192 | IARG_END); 193 | 194 | RTN_Close(mallocRtn); 195 | } 196 | 197 | if (RTN_Valid(freeRtn)){ 198 | RTN_Open(freeRtn); 199 | RTN_InsertCall( 200 | freeRtn, 201 | IPOINT_BEFORE, (AFUNPTR)callbackBeforeFree, 202 | IARG_FUNCARG_ENTRYPOINT_VALUE, 0, 203 | IARG_END); 204 | RTN_Close(freeRtn); 205 | } 206 | } 207 | 208 | int main(int argc, char *argv[]) 209 | { 210 | PIN_InitSymbols(); 211 | if(PIN_Init(argc, argv)){ 212 | return Usage(); 213 | } 214 | 215 | PIN_SetSyntaxIntel(); 216 | IMG_AddInstrumentFunction(Image, 0); 217 | INS_AddInstrumentFunction(Instruction, 0); 218 | PIN_StartProgram(); 219 | 220 | return 0; 221 | } 222 | 223 | -------------------------------------------------------------------------------- /PointerWithoutCheckDetection/crackme: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/PointerWithoutCheckDetection/crackme -------------------------------------------------------------------------------- /PointerWithoutCheckDetection/crackme.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Jonathan Salwan - Copyright (C) 2013-07 3 | ** 4 | ** http://twitter.com/JonathanSalwan 5 | ** http://shell-storm.org 6 | ** 7 | ** This program is free software: you can redistribute it and/or modify 8 | ** it under the terms of the GNU General Public License as published by 9 | ** the Free Software Foundation, either version 3 of the License, or 10 | ** (at your option) any later version. 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | char *serial = "\x30\x39\x3c\x21\x30"; 19 | 20 | int main(void) 21 | { 22 | int fd, i = 0; 23 | char *buf; 24 | char *r; 25 | 26 | buf = malloc(256); 27 | if (!buf) 28 | return -1; 29 | r = buf; 30 | fd = open("serial.txt", O_RDONLY); 31 | read(fd, buf, 256); 32 | close(fd); 33 | while (i < 5){ 34 | if ((*buf ^ 0x55) != *serial) 35 | return 0; 36 | buf++, serial++, i++; 37 | } 38 | if (!*buf) 39 | printf("Good boy\n"); 40 | free(r); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /PointerWithoutCheckDetection/file.txt: -------------------------------------------------------------------------------- 1 | ABCD 2 | -------------------------------------------------------------------------------- /PointerWithoutCheckDetection/makefile: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # DO NOT EDIT THIS FILE! 4 | # 5 | ############################################################## 6 | 7 | # If the tool is built out of the kit, PIN_ROOT must be specified in the make invocation and point to the kit root. 8 | ifdef PIN_ROOT 9 | CONFIG_ROOT := $(PIN_ROOT)/source/tools/Config 10 | else 11 | CONFIG_ROOT := ../Config 12 | endif 13 | include $(CONFIG_ROOT)/makefile.config 14 | include makefile.rules 15 | include $(TOOLS_ROOT)/Config/makefile.default.rules 16 | 17 | ############################################################## 18 | # 19 | # DO NOT EDIT THIS FILE! 20 | # 21 | ############################################################## 22 | -------------------------------------------------------------------------------- /PointerWithoutCheckDetection/makefile.rules: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # This file includes all the test targets as well as all the 4 | # non-default build rules and test recipes. 5 | # 6 | ############################################################## 7 | 8 | 9 | ############################################################## 10 | # 11 | # Test targets 12 | # 13 | ############################################################## 14 | 15 | ###### Place all generic definitions here ###### 16 | 17 | # This defines tests which run tools of the same name. This is simply for convenience to avoid 18 | # defining the test name twice (once in TOOL_ROOTS and again in TEST_ROOTS). 19 | # Tests defined here should not be defined in TOOL_ROOTS and TEST_ROOTS. 20 | TEST_TOOL_ROOTS := Taint 21 | 22 | # This defines the tests to be run that were not already defined in TEST_TOOL_ROOTS. 23 | TEST_ROOTS := 24 | 25 | # This defines a list of tests that should run in the "short" sanity. Tests in this list must also 26 | # appear either in the TEST_TOOL_ROOTS or the TEST_ROOTS list. 27 | # If the entire directory should be tested in sanity, assign TEST_TOOL_ROOTS and TEST_ROOTS to the 28 | # SANITY_SUBSET variable in the tests section below (see example in makefile.rules.tmpl). 29 | SANITY_SUBSET := 30 | 31 | # This defines the tools which will be run during the the tests, and were not already defined in 32 | # TEST_TOOL_ROOTS. 33 | TOOL_ROOTS := 34 | 35 | # This defines the static analysis tools which will be run during the the tests. They should not 36 | # be defined in TEST_TOOL_ROOTS. If a test with the same name exists, it should be defined in 37 | # TEST_ROOTS. 38 | # Note: Static analysis tools are in fact executables linked with the Pin Static Analysis Library. 39 | # This library provides a subset of the Pin APIs which allows the tool to perform static analysis 40 | # of an application or dll. Pin itself is not used when this tool runs. 41 | SA_TOOL_ROOTS := 42 | 43 | # This defines all the applications that will be run during the tests. 44 | APP_ROOTS := 45 | 46 | # This defines any additional object files that need to be compiled. 47 | OBJECT_ROOTS := 48 | 49 | # This defines any additional dlls (shared objects), other than the pintools, that need to be compiled. 50 | DLL_ROOTS := 51 | 52 | # This defines any static libraries (archives), that need to be built. 53 | LIB_ROOTS := 54 | 55 | 56 | ############################################################## 57 | # 58 | # Test recipes 59 | # 60 | ############################################################## 61 | 62 | # This section contains recipes for tests other than the default. 63 | # See makefile.default.rules for the default test rules. 64 | # All tests in this section should adhere to the naming convention: .test 65 | 66 | 67 | ############################################################## 68 | # 69 | # Build rules 70 | # 71 | ############################################################## 72 | 73 | # This section contains the build rules for all binaries that have special build rules. 74 | # See makefile.default.rules for the default build rules. 75 | -------------------------------------------------------------------------------- /PointerWithoutCheckDetection/out: -------------------------------------------------------------------------------- 1 | [INFO] malloc(5) = 1a54010 2 | [READ in 1a54010 without check] 7fc4ae376544: mov byte ptr [rdi], cl 3 | [READ in 1a54010 without check] ffffffffffffffff: mov qword ptr [r15+0x60], rax 4 | [READ in 1a54010 without check] ffffffffffffffff: mov rdi, 0x7fc4ae97185e 5 | [READ in 1a54010 without check] ffffffffffffffff: mov r11, 0x7fc4c041ffe0 6 | [READ in 1a54010 without check] 7fc4ae3cb52e: mov ecx, dword ptr [rsi] 7 | [INFO] free(1a54010) 8 | [READ in 1a54010 without check] 7fc4ae3beccb: mov qword ptr [rbx+0x10], rdx 9 | [INFO] malloc(78) = 1a54030 10 | [READ in 1a54010 without check] 7fc4ae3bf77f: mov r8, qword ptr [r14+0x10] 11 | [INFO] malloc(c) = 1a54010 12 | [READ in 1a54010 without check] ffffffffffffffff: mov rdi, 0x7fc4ae974a58 13 | [READ in 1a54030 without check] 7fc4ae370afe: mov qword ptr [r12], rax 14 | [INFO] malloc(308) = 1a540b0 15 | [READ in 1a540b0 without check] 7fc4ae370b52: mov qword ptr [rax], rdx 16 | [INFO] malloc(70) = 1a543c0 17 | [READ in 1a543c0 without check] 7fc4ae370b52: mov qword ptr [rax], rdx 18 | [INFO] malloc(3b8) = 1a54440 19 | [READ in 1a54440 without check] 7fc4ae370b52: mov qword ptr [rax], rdx 20 | [INFO] malloc(d8) = 1a54800 21 | [READ in 1a54800 without check] 7fc4ae370b52: mov qword ptr [rax], rdx 22 | [INFO] malloc(1b0) = 1a548e0 23 | [READ in 1a548e0 without check] 7fc4ae370b52: mov qword ptr [rax], rdx 24 | [INFO] malloc(68) = 1a54aa0 25 | [READ in 1a54aa0 without check] 7fc4ae370b52: mov qword ptr [rax], rdx 26 | [INFO] malloc(58) = 1a54b10 27 | [READ in 1a54b10 without check] 7fc4ae370b52: mov qword ptr [rax], rdx 28 | [INFO] malloc(78) = 1a54b70 29 | [READ in 1a54b70 without check] 7fc4ae370b52: mov qword ptr [rax], rdx 30 | [INFO] malloc(a8) = 1a54bf0 31 | [READ in 1a54bf0 without check] 7fc4ae370b52: mov qword ptr [rax], rdx 32 | [INFO] malloc(68) = 1a54ca0 33 | [READ in 1a54ca0 without check] 7fc4ae370b52: mov qword ptr [rax], rdx 34 | [INFO] malloc(50) = 1a54d10 35 | [READ in 1a54d10 without check] 7fc4ae370b52: mov qword ptr [rax], rdx 36 | [INFO] malloc(c0) = 1a54d70 37 | [READ in 1a54d70 without check] 7fc4ae370b52: mov qword ptr [rax], rdx 38 | [READ in 1a54010 without check] ffffffffffffffff: mov rax, qword ptr [r15+0x60] 39 | [READ in 1a54010 without check] ffffffffffffffff: call r11 40 | [READ in 1a54010 without check] ffffffffffffffff: lea rsi, ptr [r12-0x8] 41 | [INFO] malloc(c) = 1a54e40 42 | [READ in 1a54010 without check] ffffffffffffffff: jmp 0x94d0 43 | [READ in 1a54e40 without check] ffffffffffffffff: mov rdi, 0x7fc4ae974a58 44 | [READ in 1a54010 without check] ffffffffffffffff: mov rsp, qword ptr [r15+0x770] 45 | [READ in 1a54010 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 46 | [READ in 1a54010 without check] ffffffffffffffff: vzeroupper 47 | [READ in 1a54010 without check] ffffffffffffffff: mov qword ptr [r15+0x40], rsp 48 | [INFO] malloc(c) = 1a54e60 49 | [READ in 1a54010 without check] ffffffffffffffff: call r11 50 | [READ in 1a54e60 without check] ffffffffffffffff: mov rdi, 0x7fc4ae974a58 51 | [READ in 1a54010 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 52 | [READ in 1a54010 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 53 | [READ in 1a54010 without check] ffffffffffffffff: vzeroupper 54 | [READ in 1a54010 without check] ffffffffffffffff: mov qword ptr [r15+0x40], rsp 55 | [INFO] malloc(c) = 1a54e80 56 | [READ in 1a54010 without check] ffffffffffffffff: call r11 57 | [READ in 1a54e80 without check] ffffffffffffffff: mov rdi, 0x7fc4ae974a58 58 | [READ in 1a54010 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 59 | [READ in 1a54010 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 60 | [READ in 1a54010 without check] ffffffffffffffff: vzeroupper 61 | [READ in 1a54010 without check] ffffffffffffffff: mov qword ptr [r15+0x40], rsp 62 | [INFO] malloc(c) = 1a54ea0 63 | [READ in 1a54010 without check] ffffffffffffffff: call r11 64 | [READ in 1a54ea0 without check] ffffffffffffffff: mov rdi, 0x7fc4ae974a58 65 | [READ in 1a54010 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 66 | [READ in 1a54010 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 67 | [READ in 1a54010 without check] ffffffffffffffff: vzeroupper 68 | [READ in 1a54010 without check] ffffffffffffffff: mov qword ptr [r15+0x40], rsp 69 | [INFO] malloc(c) = 1a54ec0 70 | [READ in 1a54010 without check] ffffffffffffffff: call r11 71 | [READ in 1a54ec0 without check] ffffffffffffffff: mov rdi, 0x7fc4ae974a58 72 | [READ in 1a54010 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 73 | [READ in 1a54010 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 74 | [READ in 1a54010 without check] ffffffffffffffff: vzeroupper 75 | [READ in 1a54010 without check] ffffffffffffffff: mov qword ptr [r15+0x40], rsp 76 | [INFO] malloc(c) = 1a54ee0 77 | [READ in 1a54010 without check] ffffffffffffffff: call r11 78 | [READ in 1a54ee0 without check] ffffffffffffffff: mov rdi, 0x7fc4ae974a58 79 | [READ in 1a54010 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 80 | [READ in 1a54010 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 81 | [READ in 1a54010 without check] ffffffffffffffff: vzeroupper 82 | [READ in 1a54010 without check] ffffffffffffffff: mov qword ptr [r15+0x40], rsp 83 | [INFO] malloc(c) = 1a54f00 84 | [READ in 1a54010 without check] ffffffffffffffff: call r11 85 | [READ in 1a54f00 without check] ffffffffffffffff: mov rdi, 0x7fc4ae974a58 86 | [READ in 1a54010 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 87 | [READ in 1a54010 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 88 | [READ in 1a54010 without check] ffffffffffffffff: vzeroupper 89 | [READ in 1a54010 without check] ffffffffffffffff: mov qword ptr [r15+0x40], rsp 90 | [INFO] malloc(c) = 1a54f20 91 | [READ in 1a54010 without check] ffffffffffffffff: call r11 92 | [READ in 1a54f20 without check] ffffffffffffffff: mov rdi, 0x7fc4ae974a58 93 | [READ in 1a54010 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 94 | [READ in 1a54010 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 95 | [READ in 1a54010 without check] ffffffffffffffff: vzeroupper 96 | [READ in 1a54010 without check] ffffffffffffffff: mov qword ptr [r15+0x40], rsp 97 | [INFO] malloc(c) = 1a54f40 98 | [READ in 1a54010 without check] ffffffffffffffff: call r11 99 | [READ in 1a54f40 without check] ffffffffffffffff: mov rdi, 0x7fc4ae974a58 100 | [READ in 1a54010 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 101 | [READ in 1a54010 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 102 | [READ in 1a54010 without check] ffffffffffffffff: vzeroupper 103 | [READ in 1a54010 without check] ffffffffffffffff: mov qword ptr [r15+0x40], rsp 104 | [INFO] malloc(c) = 1a54f60 105 | [READ in 1a54010 without check] ffffffffffffffff: call r11 106 | [READ in 1a54f60 without check] ffffffffffffffff: mov rdi, 0x7fc4ae974a58 107 | [READ in 1a54010 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 108 | [READ in 1a54010 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 109 | [READ in 1a54010 without check] ffffffffffffffff: vzeroupper 110 | [READ in 1a54010 without check] ffffffffffffffff: mov qword ptr [r15+0x40], rsp 111 | [INFO] malloc(c) = 1a54f80 112 | [READ in 1a54010 without check] ffffffffffffffff: call r11 113 | [READ in 1a54f80 without check] ffffffffffffffff: mov rdi, 0x7fc4ae974a58 114 | [READ in 1a54010 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 115 | [READ in 1a54010 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 116 | [READ in 1a54010 without check] ffffffffffffffff: vzeroupper 117 | [READ in 1a54010 without check] ffffffffffffffff: mov qword ptr [r15+0x40], rsp 118 | [INFO] malloc(c) = 1a54fa0 119 | [READ in 1a54010 without check] ffffffffffffffff: call r11 120 | [READ in 1a54fa0 without check] ffffffffffffffff: mov rdi, 0x7fc4ae974a58 121 | [READ in 1a54fa0 without check] ffffffffffffffff: vzeroupper 122 | [READ in 1a54f80 without check] ffffffffffffffff: call r11 123 | [READ in 1a54f80 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 124 | [READ in 1a54fa0 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 125 | [READ in 1a54f60 without check] 7fc4ae36f437: add ebp, 0x1 126 | [READ in 1a54f60 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 127 | [READ in 1a54fa0 without check] ffffffffffffffff: mov qword ptr [r15+0x40], rsp 128 | [READ in 1a54f40 without check] 7fc4ae36f437: add ebp, 0x1 129 | [READ in 1a54f40 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 130 | [READ in 1a54fa0 without check] ffffffffffffffff: mov qword ptr [r15+0x40], rsp 131 | [READ in 1a54f20 without check] 7fc4ae36f437: add ebp, 0x1 132 | [READ in 1a54f20 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 133 | [READ in 1a54fa0 without check] ffffffffffffffff: mov qword ptr [r15+0x40], rsp 134 | [READ in 1a54f00 without check] 7fc4ae36f437: add ebp, 0x1 135 | [READ in 1a54f00 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 136 | [READ in 1a54fa0 without check] ffffffffffffffff: mov qword ptr [r15+0x40], rsp 137 | [READ in 1a54ee0 without check] ffffffffffffffff: nop dword ptr [rax], eax 138 | [READ in 1a54ee0 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 139 | [READ in 1a54fa0 without check] ffffffffffffffff: cld 140 | [READ in 1a54ec0 without check] ffffffffffffffff: nop dword ptr [rax], eax 141 | [READ in 1a54ec0 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 142 | [READ in 1a54fa0 without check] ffffffffffffffff: cld 143 | [READ in 1a54ea0 without check] ffffffffffffffff: nop dword ptr [rax], eax 144 | [READ in 1a54ea0 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 145 | [READ in 1a54fa0 without check] ffffffffffffffff: cld 146 | [READ in 1a54e80 without check] ffffffffffffffff: nop dword ptr [rax], eax 147 | [READ in 1a54e80 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 148 | [READ in 1a54fa0 without check] ffffffffffffffff: cld 149 | [READ in 1a54e60 without check] ffffffffffffffff: nop dword ptr [rax], eax 150 | [READ in 1a54e60 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 151 | [READ in 1a54fa0 without check] ffffffffffffffff: cld 152 | [READ in 1a54e40 without check] ffffffffffffffff: nop dword ptr [rax], eax 153 | [READ in 1a54e40 without check] ffffffffffffffff: mov r11, 0x7fc4c04201a0 154 | [READ in 1a54fa0 without check] ffffffffffffffff: cld 155 | -------------------------------------------------------------------------------- /PointerWithoutCheckDetection/pin.log: -------------------------------------------------------------------------------- 1 | Pin 2.12 kit 58423 2 | A: Source/pin/vm_ia32/jit_iarg_ia32.cpp:SetupArgument:SetupArgument:3226: assertion failed: argreg != REG_INVALID() 3 | 4 | -------------------------------------------------------------------------------- /PointerWithoutCheckDetection/pintool.log: -------------------------------------------------------------------------------- 1 | Pin 2.12 kit 58423 2 | A: Source/pin/pin/image.cpp:RTN_Open:RTN_Open:3417: Must use RTN_Close on previous rtn before opening a new rtn 3 | 4 | -------------------------------------------------------------------------------- /PointerWithoutCheckDetection/test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/PointerWithoutCheckDetection/test -------------------------------------------------------------------------------- /PointerWithoutCheckDetection/test.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main(int ac, char **av) 9 | { 10 | char c, *buf; 11 | 12 | buf = malloc(32); 13 | c = buf[0]; 14 | printf("%x\n", c); 15 | } 16 | -------------------------------------------------------------------------------- /PointerWithoutCheckDetection/test2.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/PointerWithoutCheckDetection/test2.c -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Pin Tools 2 | ========= 3 | 4 | I just decided to centralize my old and next Pin tools about program analysis in this repo. Be careful, these 5 | pintool are not reliable. They are here just as PoC and to provide some ideas. 6 | 7 | Timeline 8 | -------- 9 | 10 | +-------------------------------------------------------------------------------+ 11 | | Timeline | 12 | +----------------------------------------------------------------+--------------+ 13 | | Name | date | 14 | +================================================================+==============+ 15 | | Talks/SSTIC-2015 Triton a Pin-based DSE framewok | Jun 03, 2015 | 16 | +----------------------------------------------------------------+--------------+ 17 | | Talks/StHack-2015 Dynamic Behavior Analysis using DBI | Mar 27, 2015 | 18 | +----------------------------------------------------------------+--------------+ 19 | | Talks/SecurityDayLille-2015 Dynamic Symbolic Execution | Jan 17, 2015 | 20 | +----------------------------------------------------------------+--------------+ 21 | | FormatStringDetection | Nov 11, 2014 | 22 | +----------------------------------------------------------------+--------------+ 23 | | OverflowDetection | Oct 10, 2013 | 24 | +----------------------------------------------------------------+--------------+ 25 | | ConcolicExecution | Aug 28, 2013 | 26 | +----------------------------------------------------------------+--------------+ 27 | | InMemoryFuzzing | Aug 17, 2013 | 28 | +----------------------------------------------------------------+--------------+ 29 | | LoopDetectionInstCounter | Aug 13, 2013 | 30 | +----------------------------------------------------------------+--------------+ 31 | | ObsoleteStackFrameAccessDetection | Aug 08, 2013 | 32 | +----------------------------------------------------------------+--------------+ 33 | | ClassicalUseAfterFreePatternMatching | Aug 08, 2013 | 34 | +----------------------------------------------------------------+--------------+ 35 | | PointerWithoutCheckDetection | Aug 08, 2013 | 36 | +----------------------------------------------------------------+--------------+ 37 | | TaintAnalysis | Aug 08, 2013 | 38 | +----------------------------------------------------------------+--------------+ 39 | 40 | 41 | Related blog post 42 | ----------------- 43 | 44 | **Talks/SSTIC-2015 Triton a Pin-based concolic execution framework** 45 | 46 | - http://shell-storm.org/blog/Triton-under-the-hood/ 47 | 48 | **Talks/StHack-2015 Dynamic Behavior Analysis Using Dynamic Binary Instrumentation** 49 | 50 | - n/a 51 | 52 | **Talks/SecurityDayLille-2015 Dynamic Symbolic Execution** 53 | 54 | - http://securitydaylille1.github.io/#djo 55 | 56 | **FormatStringDetection** 57 | 58 | - n/a 59 | 60 | **OverflowDetection** 61 | 62 | - http://shell-storm.org/blog/Stack-and-heap-overflow-detection-at-runtime-via-behavior-analysis-and-PIN/ 63 | 64 | **ConcolicExecution** 65 | 66 | - http://shell-storm.org/blog/Binary-analysis-Concolic-execution-with-Pin-and-z3/ 67 | 68 | 69 | **InMemoryFuzzing** 70 | 71 | - http://shell-storm.org/blog/In-Memory-fuzzing-with-Pin/ 72 | 73 | 74 | **LoopDetectionInstCounter** 75 | 76 | - n/a 77 | 78 | **ObsoleteStackFrameAccessDetection** 79 | 80 | - http://shell-storm.org/blog/Taint-analysis-and-pattern-matching-with-Pin/#5.1 81 | 82 | **ClassicalUseAfterFreePatternMatching** 83 | 84 | - http://shell-storm.org/blog/Taint-analysis-and-pattern-matching-with-Pin/#5.2 85 | 86 | **PointerWithoutCheckDetection** 87 | 88 | - http://shell-storm.org/blog/Taint-analysis-and-pattern-matching-with-Pin/#6 89 | 90 | **TaintAnalysis** 91 | 92 | - http://shell-storm.org/blog/Taint-analysis-and-pattern-matching-with-Pin/ 93 | 94 | 95 | -------------------------------------------------------------------------------- /TaintAnalysis/SimpleTaintMemoryArea/Taint.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Jonathan Salwan - Copyright (C) 2013-08 3 | // 4 | // http://shell-storm.org 5 | // http://twitter.com/JonathanSalwan 6 | // 7 | // Note: Example 1 - http://shell-storm.org/blog/Taint-analysis-with-Pin/ 8 | // Simple taint memory area from read syscall. 9 | // 10 | 11 | #include "pin.H" 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | /* bytes range tainted */ 18 | struct range 19 | { 20 | UINT64 start; 21 | UINT64 end; 22 | }; 23 | 24 | std::list bytesTainted; 25 | 26 | INT32 Usage() 27 | { 28 | cerr << "Ex 1" << endl; 29 | return -1; 30 | } 31 | 32 | VOID ReadMem(UINT64 insAddr, std::string insDis, UINT64 memOp) 33 | { 34 | list::iterator i; 35 | UINT64 addr = memOp; 36 | 37 | for(i = bytesTainted.begin(); i != bytesTainted.end(); ++i){ 38 | if (addr >= i->start && addr < i->end){ 39 | std::cout << std::hex << "[READ in " << addr << "]\t" << insAddr << ": " << insDis<< std::endl; 40 | } 41 | } 42 | } 43 | 44 | VOID WriteMem(UINT64 insAddr, std::string insDis, UINT64 memOp) 45 | { 46 | list::iterator i; 47 | UINT64 addr = memOp; 48 | 49 | for(i = bytesTainted.begin(); i != bytesTainted.end(); ++i){ 50 | if (addr >= i->start && addr < i->end){ 51 | std::cout << std::hex << "[WRITE in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 52 | } 53 | } 54 | } 55 | 56 | VOID Instruction(INS ins, VOID *v) 57 | { 58 | if (INS_MemoryOperandIsRead(ins, 0) && INS_OperandIsReg(ins, 0)){ 59 | INS_InsertCall( 60 | ins, IPOINT_BEFORE, (AFUNPTR)ReadMem, 61 | IARG_ADDRINT, INS_Address(ins), 62 | IARG_PTR, new string(INS_Disassemble(ins)), 63 | IARG_MEMORYOP_EA, 0, 64 | IARG_END); 65 | } 66 | else if (INS_MemoryOperandIsWritten(ins, 0)){ 67 | INS_InsertCall( 68 | ins, IPOINT_BEFORE, (AFUNPTR)WriteMem, 69 | IARG_ADDRINT, INS_Address(ins), 70 | IARG_PTR, new string(INS_Disassemble(ins)), 71 | IARG_MEMORYOP_EA, 0, 72 | IARG_END); 73 | } 74 | } 75 | 76 | static unsigned int lock; 77 | 78 | #define TRICKS(){if (lock++ == 0)return;} 79 | 80 | /* Taint from Syscalls */ 81 | VOID Syscall_entry(THREADID thread_id, CONTEXT *ctx, SYSCALL_STANDARD std, void *v) 82 | { 83 | struct range taint; 84 | 85 | /* Taint from read */ 86 | if (PIN_GetSyscallNumber(ctx, std) == __NR_read){ 87 | 88 | TRICKS(); 89 | 90 | taint.start = static_cast((PIN_GetSyscallArgument(ctx, std, 1))); 91 | taint.end = taint.start + static_cast((PIN_GetSyscallArgument(ctx, std, 2))); 92 | bytesTainted.push_back(taint); 93 | std::cout << "[TAINT]\t\t\tbytes tainted from " << std::hex << "0x" << taint.start << " to 0x" << taint.end << " (via read)"<< std::endl; 94 | } 95 | } 96 | 97 | int main(int argc, char *argv[]) 98 | { 99 | if(PIN_Init(argc, argv)){ 100 | return Usage(); 101 | } 102 | 103 | PIN_SetSyntaxIntel(); 104 | PIN_AddSyscallEntryFunction(Syscall_entry, 0); 105 | INS_AddInstrumentFunction(Instruction, 0); 106 | PIN_StartProgram(); 107 | 108 | return 0; 109 | } 110 | 111 | -------------------------------------------------------------------------------- /TaintAnalysis/SimpleTaintMemoryArea/crackme: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/TaintAnalysis/SimpleTaintMemoryArea/crackme -------------------------------------------------------------------------------- /TaintAnalysis/SimpleTaintMemoryArea/crackme.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Jonathan Salwan - Copyright (C) 2013-07 3 | ** 4 | ** http://twitter.com/JonathanSalwan 5 | ** http://shell-storm.org 6 | ** 7 | ** This program is free software: you can redistribute it and/or modify 8 | ** it under the terms of the GNU General Public License as published by 9 | ** the Free Software Foundation, either version 3 of the License, or 10 | ** (at your option) any later version. 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | char *serial = "\x30\x39\x3c\x21\x30"; 19 | 20 | int main(void) 21 | { 22 | int fd, i = 0; 23 | char *buf; 24 | char *r; 25 | 26 | buf = malloc(256); 27 | if (!buf) 28 | return -1; 29 | r = buf; 30 | fd = open("serial.txt", O_RDONLY); 31 | read(fd, buf, 256); 32 | close(fd); 33 | while (i < 5){ 34 | if ((*buf ^ 0x55) != *serial) 35 | return 0; 36 | buf++, serial++, i++; 37 | } 38 | if (!*buf) 39 | printf("Good boy\n"); 40 | free(r); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /TaintAnalysis/SimpleTaintMemoryArea/file.txt: -------------------------------------------------------------------------------- 1 | skdjsakhdjsahdjsahdjsadhjsakhd 2 | -------------------------------------------------------------------------------- /TaintAnalysis/SimpleTaintMemoryArea/makefile: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # DO NOT EDIT THIS FILE! 4 | # 5 | ############################################################## 6 | 7 | # If the tool is built out of the kit, PIN_ROOT must be specified in the make invocation and point to the kit root. 8 | ifdef PIN_ROOT 9 | CONFIG_ROOT := $(PIN_ROOT)/source/tools/Config 10 | else 11 | CONFIG_ROOT := ../Config 12 | endif 13 | include $(CONFIG_ROOT)/makefile.config 14 | include makefile.rules 15 | include $(TOOLS_ROOT)/Config/makefile.default.rules 16 | 17 | ############################################################## 18 | # 19 | # DO NOT EDIT THIS FILE! 20 | # 21 | ############################################################## 22 | -------------------------------------------------------------------------------- /TaintAnalysis/SimpleTaintMemoryArea/makefile.rules: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # This file includes all the test targets as well as all the 4 | # non-default build rules and test recipes. 5 | # 6 | ############################################################## 7 | 8 | 9 | ############################################################## 10 | # 11 | # Test targets 12 | # 13 | ############################################################## 14 | 15 | ###### Place all generic definitions here ###### 16 | 17 | # This defines tests which run tools of the same name. This is simply for convenience to avoid 18 | # defining the test name twice (once in TOOL_ROOTS and again in TEST_ROOTS). 19 | # Tests defined here should not be defined in TOOL_ROOTS and TEST_ROOTS. 20 | TEST_TOOL_ROOTS := Taint 21 | 22 | # This defines the tests to be run that were not already defined in TEST_TOOL_ROOTS. 23 | TEST_ROOTS := 24 | 25 | # This defines a list of tests that should run in the "short" sanity. Tests in this list must also 26 | # appear either in the TEST_TOOL_ROOTS or the TEST_ROOTS list. 27 | # If the entire directory should be tested in sanity, assign TEST_TOOL_ROOTS and TEST_ROOTS to the 28 | # SANITY_SUBSET variable in the tests section below (see example in makefile.rules.tmpl). 29 | SANITY_SUBSET := 30 | 31 | # This defines the tools which will be run during the the tests, and were not already defined in 32 | # TEST_TOOL_ROOTS. 33 | TOOL_ROOTS := 34 | 35 | # This defines the static analysis tools which will be run during the the tests. They should not 36 | # be defined in TEST_TOOL_ROOTS. If a test with the same name exists, it should be defined in 37 | # TEST_ROOTS. 38 | # Note: Static analysis tools are in fact executables linked with the Pin Static Analysis Library. 39 | # This library provides a subset of the Pin APIs which allows the tool to perform static analysis 40 | # of an application or dll. Pin itself is not used when this tool runs. 41 | SA_TOOL_ROOTS := 42 | 43 | # This defines all the applications that will be run during the tests. 44 | APP_ROOTS := 45 | 46 | # This defines any additional object files that need to be compiled. 47 | OBJECT_ROOTS := 48 | 49 | # This defines any additional dlls (shared objects), other than the pintools, that need to be compiled. 50 | DLL_ROOTS := 51 | 52 | # This defines any static libraries (archives), that need to be built. 53 | LIB_ROOTS := 54 | 55 | 56 | ############################################################## 57 | # 58 | # Test recipes 59 | # 60 | ############################################################## 61 | 62 | # This section contains recipes for tests other than the default. 63 | # See makefile.default.rules for the default test rules. 64 | # All tests in this section should adhere to the naming convention: .test 65 | 66 | 67 | ############################################################## 68 | # 69 | # Build rules 70 | # 71 | ############################################################## 72 | 73 | # This section contains the build rules for all binaries that have special build rules. 74 | # See makefile.default.rules for the default build rules. 75 | -------------------------------------------------------------------------------- /TaintAnalysis/SimpleTaintMemoryArea/pin.log: -------------------------------------------------------------------------------- 1 | Pin 2.12 kit 58423 2 | E: Taint.cpp:113: IARG_MEMORYOP_EA/IARG_MEMORYOP_MASKED_ON invalid memory operand index (0) on 125 0x00007f91eb5dc0b3 nop dword ptr [rax+rax*1], eax 3 | -------------------------------------------------------------------------------- /TaintAnalysis/SimpleTaintMemoryArea/pintool.log: -------------------------------------------------------------------------------- 1 | Pin 2.12 kit 58423 2 | A: Source/pin/core_ia32/operand_ia32.cpp:INS_OperandIsReg:INS_OperandIsReg:356: assertion failed: n < xed_inst_noperands(xedi) 3 | 4 | -------------------------------------------------------------------------------- /TaintAnalysis/SimpleTaintMemoryArea/serial.txt: -------------------------------------------------------------------------------- 1 | elite -------------------------------------------------------------------------------- /TaintAnalysis/SimpleTaintMemoryArea/test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/TaintAnalysis/SimpleTaintMemoryArea/test -------------------------------------------------------------------------------- /TaintAnalysis/SimpleTaintMemoryArea/test.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | void foo(char *buf) 9 | { 10 | char a; 11 | 12 | a = buf[0]; 13 | a = buf[4]; 14 | a = buf[8]; 15 | a = buf[10]; 16 | buf[5] = 't'; 17 | buf[10] = 'e'; 18 | buf[20] = 's'; 19 | buf[30] = 't'; 20 | } 21 | 22 | int main(int ac, char **av) 23 | { 24 | int fd; 25 | char *buf; 26 | 27 | if (!(buf = malloc(256))) 28 | return -1; 29 | 30 | fd = open("./file.txt", O_RDONLY); 31 | read(fd, buf, 256), close(fd); 32 | foo(buf); 33 | } 34 | -------------------------------------------------------------------------------- /TaintAnalysis/SimpleTaintMemoryArea/test2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/TaintAnalysis/SimpleTaintMemoryArea/test2 -------------------------------------------------------------------------------- /TaintAnalysis/SimpleTaintMemoryArea/test2.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | void foo(char *buf) 9 | { 10 | if (buf[0] != 'a') 11 | return ; 12 | if (buf[1] != 'b') 13 | return ; 14 | if (buf[2] != 'c') 15 | return ; 16 | if (buf[3] != 'd') 17 | return ; 18 | if (buf[4] != 'e') 19 | return ; 20 | 21 | printf("Good boy\n"); 22 | } 23 | 24 | char *test_stack_frame; 25 | 26 | void pre_foo(void) 27 | { 28 | int fd; 29 | 30 | char buf[256]; /* Taint on the stack - Stack Frame Test */ 31 | 32 | test_stack_frame = buf; 33 | 34 | fd = open("./serial.txt", O_RDONLY); 35 | read(fd, buf, 256); 36 | close(fd); 37 | 38 | foo(buf); 39 | } 40 | 41 | int main(int ac, char **av) 42 | { 43 | char test; 44 | 45 | pre_foo(); 46 | test = test_stack_frame[0]; /* 'test' should not be tainted ! */ 47 | } 48 | -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintAndFollowYourData/Taint.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Jonathan Salwan - Copyright (C) 2013-08 3 | // 4 | // http://shell-storm.org 5 | // http://twitter.com/JonathanSalwan 6 | // 7 | // Note: Example 3 - http://shell-storm.org/blog/Taint-analysis-with-Pin/ 8 | // Spread the taint in memory/registers and follow your data. 9 | // 10 | 11 | #include "pin.H" 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | std::list addressTainted; 18 | std::list regsTainted; 19 | 20 | INT32 Usage() 21 | { 22 | cerr << "Ex 3" << endl; 23 | return -1; 24 | } 25 | 26 | bool checkAlreadyRegTainted(REG reg) 27 | { 28 | list::iterator i; 29 | 30 | for(i = regsTainted.begin(); i != regsTainted.end(); i++){ 31 | if (*i == reg){ 32 | return true; 33 | } 34 | } 35 | return false; 36 | } 37 | 38 | VOID removeMemTainted(UINT64 addr) 39 | { 40 | addressTainted.remove(addr); 41 | std::cout << std::hex << "\t\t\t" << addr << " is now freed" << std::endl; 42 | } 43 | 44 | VOID addMemTainted(UINT64 addr) 45 | { 46 | addressTainted.push_back(addr); 47 | std::cout << std::hex << "\t\t\t" << addr << " is now tainted" << std::endl; 48 | } 49 | 50 | bool taintReg(REG reg) 51 | { 52 | if (checkAlreadyRegTainted(reg) == true){ 53 | std::cout << "\t\t\t" << REG_StringShort(reg) << " is already tainted" << std::endl; 54 | return false; 55 | } 56 | 57 | switch(reg){ 58 | 59 | case REG_RAX: regsTainted.push_front(REG_RAX); 60 | case REG_EAX: regsTainted.push_front(REG_EAX); 61 | case REG_AX: regsTainted.push_front(REG_AX); 62 | case REG_AH: regsTainted.push_front(REG_AH); 63 | case REG_AL: regsTainted.push_front(REG_AL); 64 | break; 65 | 66 | case REG_RBX: regsTainted.push_front(REG_RBX); 67 | case REG_EBX: regsTainted.push_front(REG_EBX); 68 | case REG_BX: regsTainted.push_front(REG_BX); 69 | case REG_BH: regsTainted.push_front(REG_BH); 70 | case REG_BL: regsTainted.push_front(REG_BL); 71 | break; 72 | 73 | case REG_RCX: regsTainted.push_front(REG_RCX); 74 | case REG_ECX: regsTainted.push_front(REG_ECX); 75 | case REG_CX: regsTainted.push_front(REG_CX); 76 | case REG_CH: regsTainted.push_front(REG_CH); 77 | case REG_CL: regsTainted.push_front(REG_CL); 78 | break; 79 | 80 | case REG_RDX: regsTainted.push_front(REG_RDX); 81 | case REG_EDX: regsTainted.push_front(REG_EDX); 82 | case REG_DX: regsTainted.push_front(REG_DX); 83 | case REG_DH: regsTainted.push_front(REG_DH); 84 | case REG_DL: regsTainted.push_front(REG_DL); 85 | break; 86 | 87 | case REG_RDI: regsTainted.push_front(REG_RDI); 88 | case REG_EDI: regsTainted.push_front(REG_EDI); 89 | case REG_DI: regsTainted.push_front(REG_DI); 90 | case REG_DIL: regsTainted.push_front(REG_DIL); 91 | break; 92 | 93 | case REG_RSI: regsTainted.push_front(REG_RSI); 94 | case REG_ESI: regsTainted.push_front(REG_ESI); 95 | case REG_SI: regsTainted.push_front(REG_SI); 96 | case REG_SIL: regsTainted.push_front(REG_SIL); 97 | break; 98 | 99 | default: 100 | std::cout << "\t\t\t" << REG_StringShort(reg) << " can't be tainted" << std::endl; 101 | return false; 102 | } 103 | std::cout << "\t\t\t" << REG_StringShort(reg) << " is now tainted" << std::endl; 104 | return true; 105 | } 106 | 107 | bool removeRegTainted(REG reg) 108 | { 109 | switch(reg){ 110 | 111 | case REG_RAX: regsTainted.remove(REG_RAX); 112 | case REG_EAX: regsTainted.remove(REG_EAX); 113 | case REG_AX: regsTainted.remove(REG_AX); 114 | case REG_AH: regsTainted.remove(REG_AH); 115 | case REG_AL: regsTainted.remove(REG_AL); 116 | break; 117 | 118 | case REG_RBX: regsTainted.remove(REG_RBX); 119 | case REG_EBX: regsTainted.remove(REG_EBX); 120 | case REG_BX: regsTainted.remove(REG_BX); 121 | case REG_BH: regsTainted.remove(REG_BH); 122 | case REG_BL: regsTainted.remove(REG_BL); 123 | break; 124 | 125 | case REG_RCX: regsTainted.remove(REG_RCX); 126 | case REG_ECX: regsTainted.remove(REG_ECX); 127 | case REG_CX: regsTainted.remove(REG_CX); 128 | case REG_CH: regsTainted.remove(REG_CH); 129 | case REG_CL: regsTainted.remove(REG_CL); 130 | break; 131 | 132 | case REG_RDX: regsTainted.remove(REG_RDX); 133 | case REG_EDX: regsTainted.remove(REG_EDX); 134 | case REG_DX: regsTainted.remove(REG_DX); 135 | case REG_DH: regsTainted.remove(REG_DH); 136 | case REG_DL: regsTainted.remove(REG_DL); 137 | break; 138 | 139 | case REG_RDI: regsTainted.remove(REG_RDI); 140 | case REG_EDI: regsTainted.remove(REG_EDI); 141 | case REG_DI: regsTainted.remove(REG_DI); 142 | case REG_DIL: regsTainted.remove(REG_DIL); 143 | break; 144 | 145 | case REG_RSI: regsTainted.remove(REG_RSI); 146 | case REG_ESI: regsTainted.remove(REG_ESI); 147 | case REG_SI: regsTainted.remove(REG_SI); 148 | case REG_SIL: regsTainted.remove(REG_SIL); 149 | break; 150 | 151 | default: 152 | return false; 153 | } 154 | std::cout << "\t\t\t" << REG_StringShort(reg) << " is now freed" << std::endl; 155 | return true; 156 | } 157 | 158 | VOID ReadMem(UINT64 insAddr, std::string insDis, UINT32 opCount, REG reg_r, UINT64 memOp) 159 | { 160 | list::iterator i; 161 | UINT64 addr = memOp; 162 | 163 | if (opCount != 2) 164 | return; 165 | 166 | for(i = addressTainted.begin(); i != addressTainted.end(); i++){ 167 | if (addr == *i){ 168 | std::cout << std::hex << "[READ in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 169 | taintReg(reg_r); 170 | return ; 171 | } 172 | } 173 | /* if mem != tained and reg == taint => free the reg */ 174 | if (checkAlreadyRegTainted(reg_r)){ 175 | std::cout << std::hex << "[READ in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 176 | removeRegTainted(reg_r); 177 | } 178 | } 179 | 180 | VOID WriteMem(UINT64 insAddr, std::string insDis, UINT32 opCount, REG reg_r, UINT64 memOp) 181 | { 182 | list::iterator i; 183 | UINT64 addr = memOp; 184 | 185 | if (opCount != 2) 186 | return; 187 | 188 | for(i = addressTainted.begin(); i != addressTainted.end(); i++){ 189 | if (addr == *i){ 190 | std::cout << std::hex << "[WRITE in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 191 | if (!REG_valid(reg_r) || !checkAlreadyRegTainted(reg_r)) 192 | removeMemTainted(addr); 193 | return ; 194 | } 195 | } 196 | if (checkAlreadyRegTainted(reg_r)){ 197 | std::cout << std::hex << "[WRITE in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 198 | addMemTainted(addr); 199 | } 200 | } 201 | 202 | VOID spreadRegTaint(UINT64 insAddr, std::string insDis, UINT32 opCount, REG reg_r, REG reg_w) 203 | { 204 | if (opCount != 2) 205 | return; 206 | 207 | if (REG_valid(reg_w)){ 208 | if (checkAlreadyRegTainted(reg_w) && (!REG_valid(reg_r) || !checkAlreadyRegTainted(reg_r))){ 209 | std::cout << "[SPREAD]\t\t" << insAddr << ": " << insDis << std::endl; 210 | std::cout << "\t\t\toutput: "<< REG_StringShort(reg_w) << " | input: " << (REG_valid(reg_r) ? REG_StringShort(reg_r) : "constant") << std::endl; 211 | removeRegTainted(reg_w); 212 | } 213 | else if (!checkAlreadyRegTainted(reg_w) && checkAlreadyRegTainted(reg_r)){ 214 | std::cout << "[SPREAD]\t\t" << insAddr << ": " << insDis << std::endl; 215 | std::cout << "\t\t\toutput: " << REG_StringShort(reg_w) << " | input: "<< REG_StringShort(reg_r) << std::endl; 216 | taintReg(reg_w); 217 | } 218 | } 219 | } 220 | 221 | VOID followData(UINT64 insAddr, std::string insDis, REG reg) 222 | { 223 | if (!REG_valid(reg)) 224 | return; 225 | 226 | if (checkAlreadyRegTainted(reg)){ 227 | std::cout << "[FOLLOW]\t\t" << insAddr << ": " << insDis << std::endl; 228 | } 229 | } 230 | 231 | VOID Instruction(INS ins, VOID *v) 232 | { 233 | if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsRead(ins, 0) && INS_OperandIsReg(ins, 0)){ 234 | INS_InsertCall( 235 | ins, IPOINT_BEFORE, (AFUNPTR)ReadMem, 236 | IARG_ADDRINT, INS_Address(ins), 237 | IARG_PTR, new string(INS_Disassemble(ins)), 238 | IARG_UINT32, INS_OperandCount(ins), 239 | IARG_UINT32, INS_OperandReg(ins, 0), 240 | IARG_MEMORYOP_EA, 0, 241 | IARG_END); 242 | } 243 | else if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsWritten(ins, 0)){ 244 | INS_InsertCall( 245 | ins, IPOINT_BEFORE, (AFUNPTR)WriteMem, 246 | IARG_ADDRINT, INS_Address(ins), 247 | IARG_PTR, new string(INS_Disassemble(ins)), 248 | IARG_UINT32, INS_OperandCount(ins), 249 | IARG_UINT32, INS_OperandReg(ins, 1), 250 | IARG_MEMORYOP_EA, 0, 251 | IARG_END); 252 | } 253 | else if (INS_OperandCount(ins) > 1 && INS_OperandIsReg(ins, 0)){ 254 | INS_InsertCall( 255 | ins, IPOINT_BEFORE, (AFUNPTR)spreadRegTaint, 256 | IARG_ADDRINT, INS_Address(ins), 257 | IARG_PTR, new string(INS_Disassemble(ins)), 258 | IARG_UINT32, INS_OperandCount(ins), 259 | IARG_UINT32, INS_RegR(ins, 0), 260 | IARG_UINT32, INS_RegW(ins, 0), 261 | IARG_END); 262 | } 263 | 264 | if (INS_OperandCount(ins) > 1 && INS_OperandIsReg(ins, 0)){ 265 | INS_InsertCall( 266 | ins, IPOINT_BEFORE, (AFUNPTR)followData, 267 | IARG_ADDRINT, INS_Address(ins), 268 | IARG_PTR, new string(INS_Disassemble(ins)), 269 | IARG_UINT32, INS_RegR(ins, 0), 270 | IARG_END); 271 | } 272 | } 273 | 274 | static unsigned int tryksOpen; 275 | 276 | #define TRICKS(){if (tryksOpen++ == 0)return;} 277 | 278 | VOID Syscall_entry(THREADID thread_id, CONTEXT *ctx, SYSCALL_STANDARD std, void *v) 279 | { 280 | unsigned int i; 281 | UINT64 start, size; 282 | 283 | if (PIN_GetSyscallNumber(ctx, std) == __NR_read){ 284 | 285 | TRICKS(); /* tricks to ignore the first open */ 286 | 287 | start = static_cast((PIN_GetSyscallArgument(ctx, std, 1))); 288 | size = static_cast((PIN_GetSyscallArgument(ctx, std, 2))); 289 | 290 | for (i = 0; i < size; i++) 291 | addressTainted.push_back(start+i); 292 | 293 | std::cout << "[TAINT]\t\t\tbytes tainted from " << std::hex << "0x" << start << " to 0x" << start+size << " (via read)"<< std::endl; 294 | } 295 | } 296 | 297 | int main(int argc, char *argv[]) 298 | { 299 | if(PIN_Init(argc, argv)){ 300 | return Usage(); 301 | } 302 | 303 | PIN_SetSyntaxIntel(); 304 | PIN_AddSyscallEntryFunction(Syscall_entry, 0); 305 | INS_AddInstrumentFunction(Instruction, 0); 306 | PIN_StartProgram(); 307 | 308 | return 0; 309 | } 310 | 311 | -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintAndFollowYourData/crackme: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/TaintAnalysis/SpreadTheTaintAndFollowYourData/crackme -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintAndFollowYourData/crackme.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Jonathan Salwan - Copyright (C) 2013-07 3 | ** 4 | ** http://twitter.com/JonathanSalwan 5 | ** http://shell-storm.org 6 | ** 7 | ** This program is free software: you can redistribute it and/or modify 8 | ** it under the terms of the GNU General Public License as published by 9 | ** the Free Software Foundation, either version 3 of the License, or 10 | ** (at your option) any later version. 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | char *serial = "\x30\x39\x3c\x21\x30"; 19 | 20 | int main(void) 21 | { 22 | int fd, i = 0; 23 | char *buf; 24 | char *r; 25 | 26 | buf = malloc(256); 27 | if (!buf) 28 | return -1; 29 | r = buf; 30 | fd = open("serial.txt", O_RDONLY); 31 | read(fd, buf, 256); 32 | close(fd); 33 | while (i < 5){ 34 | if ((*buf ^ 0x55) != *serial) 35 | return 0; 36 | buf++, serial++, i++; 37 | } 38 | if (!*buf) 39 | printf("Good boy\n"); 40 | free(r); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintAndFollowYourData/file.txt: -------------------------------------------------------------------------------- 1 | ABCD 2 | -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintAndFollowYourData/makefile: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # DO NOT EDIT THIS FILE! 4 | # 5 | ############################################################## 6 | 7 | # If the tool is built out of the kit, PIN_ROOT must be specified in the make invocation and point to the kit root. 8 | ifdef PIN_ROOT 9 | CONFIG_ROOT := $(PIN_ROOT)/source/tools/Config 10 | else 11 | CONFIG_ROOT := ../Config 12 | endif 13 | include $(CONFIG_ROOT)/makefile.config 14 | include makefile.rules 15 | include $(TOOLS_ROOT)/Config/makefile.default.rules 16 | 17 | ############################################################## 18 | # 19 | # DO NOT EDIT THIS FILE! 20 | # 21 | ############################################################## 22 | -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintAndFollowYourData/makefile.rules: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # This file includes all the test targets as well as all the 4 | # non-default build rules and test recipes. 5 | # 6 | ############################################################## 7 | 8 | 9 | ############################################################## 10 | # 11 | # Test targets 12 | # 13 | ############################################################## 14 | 15 | ###### Place all generic definitions here ###### 16 | 17 | # This defines tests which run tools of the same name. This is simply for convenience to avoid 18 | # defining the test name twice (once in TOOL_ROOTS and again in TEST_ROOTS). 19 | # Tests defined here should not be defined in TOOL_ROOTS and TEST_ROOTS. 20 | TEST_TOOL_ROOTS := Taint 21 | 22 | # This defines the tests to be run that were not already defined in TEST_TOOL_ROOTS. 23 | TEST_ROOTS := 24 | 25 | # This defines a list of tests that should run in the "short" sanity. Tests in this list must also 26 | # appear either in the TEST_TOOL_ROOTS or the TEST_ROOTS list. 27 | # If the entire directory should be tested in sanity, assign TEST_TOOL_ROOTS and TEST_ROOTS to the 28 | # SANITY_SUBSET variable in the tests section below (see example in makefile.rules.tmpl). 29 | SANITY_SUBSET := 30 | 31 | # This defines the tools which will be run during the the tests, and were not already defined in 32 | # TEST_TOOL_ROOTS. 33 | TOOL_ROOTS := 34 | 35 | # This defines the static analysis tools which will be run during the the tests. They should not 36 | # be defined in TEST_TOOL_ROOTS. If a test with the same name exists, it should be defined in 37 | # TEST_ROOTS. 38 | # Note: Static analysis tools are in fact executables linked with the Pin Static Analysis Library. 39 | # This library provides a subset of the Pin APIs which allows the tool to perform static analysis 40 | # of an application or dll. Pin itself is not used when this tool runs. 41 | SA_TOOL_ROOTS := 42 | 43 | # This defines all the applications that will be run during the tests. 44 | APP_ROOTS := 45 | 46 | # This defines any additional object files that need to be compiled. 47 | OBJECT_ROOTS := 48 | 49 | # This defines any additional dlls (shared objects), other than the pintools, that need to be compiled. 50 | DLL_ROOTS := 51 | 52 | # This defines any static libraries (archives), that need to be built. 53 | LIB_ROOTS := 54 | 55 | 56 | ############################################################## 57 | # 58 | # Test recipes 59 | # 60 | ############################################################## 61 | 62 | # This section contains recipes for tests other than the default. 63 | # See makefile.default.rules for the default test rules. 64 | # All tests in this section should adhere to the naming convention: .test 65 | 66 | 67 | ############################################################## 68 | # 69 | # Build rules 70 | # 71 | ############################################################## 72 | 73 | # This section contains the build rules for all binaries that have special build rules. 74 | # See makefile.default.rules for the default build rules. 75 | -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintAndFollowYourData/pin.log: -------------------------------------------------------------------------------- 1 | Pin 2.12 kit 58423 2 | E: Taint.cpp:235: IARG_MEMORYOP_EA/IARG_MEMORYOP_MASKED_ON invalid memory operand index (0) on 289 0x00007f32b21c50b3 nop dword ptr [rax+rax*1], eax 3 | -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintAndFollowYourData/pintool.log: -------------------------------------------------------------------------------- 1 | Pin 2.12 kit 58423 2 | A: Source/pin/core_ia32/operand_ia32.cpp:INS_OperandIsReg:INS_OperandIsReg:356: assertion failed: n < xed_inst_noperands(xedi) 3 | 4 | -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintAndFollowYourData/test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/TaintAnalysis/SpreadTheTaintAndFollowYourData/test -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintAndFollowYourData/test.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define true 0 9 | #define false !true 10 | 11 | int foo(char *buf) 12 | { 13 | if (buf[0] != 'A') 14 | return false; 15 | if (buf[1] != 'B') 16 | return false; 17 | if (buf[2] != 'C') 18 | return false; 19 | if (buf[3] != 'D') 20 | return false; 21 | return true; 22 | } 23 | 24 | int main(int ac, char **av) 25 | { 26 | int fd; 27 | char *buf; 28 | 29 | if (!(buf = malloc(32))) 30 | return -1; 31 | 32 | fd = open("./file.txt", O_RDONLY); 33 | read(fd, buf, 32), close(fd); 34 | foo(buf); 35 | } 36 | -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintInMemoryAndRegisters/Taint.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Jonathan Salwan - Copyright (C) 2013-08 3 | // 4 | // http://shell-storm.org 5 | // http://twitter.com/JonathanSalwan 6 | // 7 | // Note: Example 2 - http://shell-storm.org/blog/Taint-analysis-with-Pin/ 8 | // Spread the taint in memory and registers. 9 | // 10 | 11 | #include "pin.H" 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | std::list addressTainted; 18 | std::list regsTainted; 19 | 20 | INT32 Usage() 21 | { 22 | cerr << "Ex 2" << endl; 23 | return -1; 24 | } 25 | 26 | bool checkAlreadyRegTainted(REG reg) 27 | { 28 | list::iterator i; 29 | 30 | for(i = regsTainted.begin(); i != regsTainted.end(); i++){ 31 | if (*i == reg){ 32 | return true; 33 | } 34 | } 35 | return false; 36 | } 37 | 38 | VOID removeMemTainted(UINT64 addr) 39 | { 40 | addressTainted.remove(addr); 41 | std::cout << std::hex << "\t\t\t" << addr << " is now freed" << std::endl; 42 | } 43 | 44 | VOID addMemTainted(UINT64 addr) 45 | { 46 | addressTainted.push_back(addr); 47 | std::cout << std::hex << "\t\t\t" << addr << " is now tainted" << std::endl; 48 | } 49 | 50 | bool taintReg(REG reg) 51 | { 52 | if (checkAlreadyRegTainted(reg) == true){ 53 | std::cout << "\t\t\t" << REG_StringShort(reg) << " is already tainted" << std::endl; 54 | return false; 55 | } 56 | 57 | switch(reg){ 58 | 59 | case REG_RAX: regsTainted.push_front(REG_RAX); 60 | case REG_EAX: regsTainted.push_front(REG_EAX); 61 | case REG_AX: regsTainted.push_front(REG_AX); 62 | case REG_AH: regsTainted.push_front(REG_AH); 63 | case REG_AL: regsTainted.push_front(REG_AL); 64 | break; 65 | 66 | case REG_RBX: regsTainted.push_front(REG_RBX); 67 | case REG_EBX: regsTainted.push_front(REG_EBX); 68 | case REG_BX: regsTainted.push_front(REG_BX); 69 | case REG_BH: regsTainted.push_front(REG_BH); 70 | case REG_BL: regsTainted.push_front(REG_BL); 71 | break; 72 | 73 | case REG_RCX: regsTainted.push_front(REG_RCX); 74 | case REG_ECX: regsTainted.push_front(REG_ECX); 75 | case REG_CX: regsTainted.push_front(REG_CX); 76 | case REG_CH: regsTainted.push_front(REG_CH); 77 | case REG_CL: regsTainted.push_front(REG_CL); 78 | break; 79 | 80 | case REG_RDX: regsTainted.push_front(REG_RDX); 81 | case REG_EDX: regsTainted.push_front(REG_EDX); 82 | case REG_DX: regsTainted.push_front(REG_DX); 83 | case REG_DH: regsTainted.push_front(REG_DH); 84 | case REG_DL: regsTainted.push_front(REG_DL); 85 | break; 86 | 87 | case REG_RDI: regsTainted.push_front(REG_RDI); 88 | case REG_EDI: regsTainted.push_front(REG_EDI); 89 | case REG_DI: regsTainted.push_front(REG_DI); 90 | case REG_DIL: regsTainted.push_front(REG_DIL); 91 | break; 92 | 93 | case REG_RSI: regsTainted.push_front(REG_RSI); 94 | case REG_ESI: regsTainted.push_front(REG_ESI); 95 | case REG_SI: regsTainted.push_front(REG_SI); 96 | case REG_SIL: regsTainted.push_front(REG_SIL); 97 | break; 98 | 99 | default: 100 | std::cout << "\t\t\t" << REG_StringShort(reg) << " can't be tainted" << std::endl; 101 | return false; 102 | } 103 | std::cout << "\t\t\t" << REG_StringShort(reg) << " is now tainted" << std::endl; 104 | return true; 105 | } 106 | 107 | bool removeRegTainted(REG reg) 108 | { 109 | switch(reg){ 110 | 111 | case REG_RAX: regsTainted.remove(REG_RAX); 112 | case REG_EAX: regsTainted.remove(REG_EAX); 113 | case REG_AX: regsTainted.remove(REG_AX); 114 | case REG_AH: regsTainted.remove(REG_AH); 115 | case REG_AL: regsTainted.remove(REG_AL); 116 | break; 117 | 118 | case REG_RBX: regsTainted.remove(REG_RBX); 119 | case REG_EBX: regsTainted.remove(REG_EBX); 120 | case REG_BX: regsTainted.remove(REG_BX); 121 | case REG_BH: regsTainted.remove(REG_BH); 122 | case REG_BL: regsTainted.remove(REG_BL); 123 | break; 124 | 125 | case REG_RCX: regsTainted.remove(REG_RCX); 126 | case REG_ECX: regsTainted.remove(REG_ECX); 127 | case REG_CX: regsTainted.remove(REG_CX); 128 | case REG_CH: regsTainted.remove(REG_CH); 129 | case REG_CL: regsTainted.remove(REG_CL); 130 | break; 131 | 132 | case REG_RDX: regsTainted.remove(REG_RDX); 133 | case REG_EDX: regsTainted.remove(REG_EDX); 134 | case REG_DX: regsTainted.remove(REG_DX); 135 | case REG_DH: regsTainted.remove(REG_DH); 136 | case REG_DL: regsTainted.remove(REG_DL); 137 | break; 138 | 139 | case REG_RDI: regsTainted.remove(REG_RDI); 140 | case REG_EDI: regsTainted.remove(REG_EDI); 141 | case REG_DI: regsTainted.remove(REG_DI); 142 | case REG_DIL: regsTainted.remove(REG_DIL); 143 | break; 144 | 145 | case REG_RSI: regsTainted.remove(REG_RSI); 146 | case REG_ESI: regsTainted.remove(REG_ESI); 147 | case REG_SI: regsTainted.remove(REG_SI); 148 | case REG_SIL: regsTainted.remove(REG_SIL); 149 | break; 150 | 151 | default: 152 | return false; 153 | } 154 | std::cout << "\t\t\t" << REG_StringShort(reg) << " is now freed" << std::endl; 155 | return true; 156 | } 157 | 158 | VOID ReadMem(UINT64 insAddr, std::string insDis, UINT32 opCount, REG reg_r, UINT64 memOp) 159 | { 160 | list::iterator i; 161 | UINT64 addr = memOp; 162 | 163 | if (opCount != 2) 164 | return; 165 | 166 | for(i = addressTainted.begin(); i != addressTainted.end(); i++){ 167 | if (addr == *i){ 168 | std::cout << std::hex << "[READ in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 169 | taintReg(reg_r); 170 | return ; 171 | } 172 | } 173 | /* if mem != tained and reg == taint => free the reg */ 174 | if (checkAlreadyRegTainted(reg_r)){ 175 | std::cout << std::hex << "[READ in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 176 | removeRegTainted(reg_r); 177 | } 178 | } 179 | 180 | VOID WriteMem(UINT64 insAddr, std::string insDis, UINT32 opCount, REG reg_r, UINT64 memOp) 181 | { 182 | list::iterator i; 183 | UINT64 addr = memOp; 184 | 185 | if (opCount != 2) 186 | return; 187 | 188 | for(i = addressTainted.begin(); i != addressTainted.end(); i++){ 189 | if (addr == *i){ 190 | std::cout << std::hex << "[WRITE in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 191 | if (!REG_valid(reg_r) || !checkAlreadyRegTainted(reg_r)) 192 | removeMemTainted(addr); 193 | return ; 194 | } 195 | } 196 | if (checkAlreadyRegTainted(reg_r)){ 197 | std::cout << std::hex << "[WRITE in " << addr << "]\t" << insAddr << ": " << insDis << std::endl; 198 | addMemTainted(addr); 199 | } 200 | } 201 | 202 | VOID spreadRegTaint(UINT64 insAddr, std::string insDis, UINT32 opCount, REG reg_r, REG reg_w) 203 | { 204 | if (opCount != 2) 205 | return; 206 | 207 | if (REG_valid(reg_w)){ 208 | if (checkAlreadyRegTainted(reg_w) && (!REG_valid(reg_r) || !checkAlreadyRegTainted(reg_r))){ 209 | std::cout << "[SPREAD]\t\t" << insAddr << ": " << insDis << std::endl; 210 | std::cout << "\t\t\toutput: "<< REG_StringShort(reg_w) << " | input: " << (REG_valid(reg_r) ? REG_StringShort(reg_r) : "constant") << std::endl; 211 | removeRegTainted(reg_w); 212 | } 213 | else if (!checkAlreadyRegTainted(reg_w) && checkAlreadyRegTainted(reg_r)){ 214 | std::cout << "[SPREAD]\t\t" << insAddr << ": " << insDis << std::endl; 215 | std::cout << "\t\t\toutput: " << REG_StringShort(reg_w) << " | input: "<< REG_StringShort(reg_r) << std::endl; 216 | taintReg(reg_w); 217 | } 218 | } 219 | } 220 | 221 | VOID Instruction(INS ins, VOID *v) 222 | { 223 | if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsRead(ins, 0) && INS_OperandIsReg(ins, 0)){ 224 | INS_InsertCall( 225 | ins, IPOINT_BEFORE, (AFUNPTR)ReadMem, 226 | IARG_ADDRINT, INS_Address(ins), 227 | IARG_PTR, new string(INS_Disassemble(ins)), 228 | IARG_UINT32, INS_OperandCount(ins), 229 | IARG_UINT32, INS_OperandReg(ins, 0), 230 | IARG_MEMORYOP_EA, 0, 231 | IARG_END); 232 | } 233 | else if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsWritten(ins, 0)){ 234 | INS_InsertCall( 235 | ins, IPOINT_BEFORE, (AFUNPTR)WriteMem, 236 | IARG_ADDRINT, INS_Address(ins), 237 | IARG_PTR, new string(INS_Disassemble(ins)), 238 | IARG_UINT32, INS_OperandCount(ins), 239 | IARG_UINT32, INS_OperandReg(ins, 1), 240 | IARG_MEMORYOP_EA, 0, 241 | IARG_END); 242 | } 243 | else if (INS_OperandCount(ins) > 1 && INS_OperandIsReg(ins, 0)){ 244 | INS_InsertCall( 245 | ins, IPOINT_BEFORE, (AFUNPTR)spreadRegTaint, 246 | IARG_ADDRINT, INS_Address(ins), 247 | IARG_PTR, new string(INS_Disassemble(ins)), 248 | IARG_UINT32, INS_OperandCount(ins), 249 | IARG_UINT32, INS_RegR(ins, 0), 250 | IARG_UINT32, INS_RegW(ins, 0), 251 | IARG_END); 252 | } 253 | } 254 | 255 | static unsigned int tryksOpen; 256 | 257 | #define TRICKS(){if (tryksOpen++ == 0)return;} 258 | 259 | VOID Syscall_entry(THREADID thread_id, CONTEXT *ctx, SYSCALL_STANDARD std, void *v) 260 | { 261 | unsigned int i; 262 | UINT64 start, size; 263 | 264 | if (PIN_GetSyscallNumber(ctx, std) == __NR_read){ 265 | 266 | TRICKS(); /* tricks to ignore the first open */ 267 | 268 | start = static_cast((PIN_GetSyscallArgument(ctx, std, 1))); 269 | size = static_cast((PIN_GetSyscallArgument(ctx, std, 2))); 270 | 271 | for (i = 0; i < size; i++) 272 | addressTainted.push_back(start+i); 273 | 274 | std::cout << "[TAINT]\t\t\tbytes tainted from " << std::hex << "0x" << start << " to 0x" << start+size << " (via read)"<< std::endl; 275 | } 276 | } 277 | 278 | int main(int argc, char *argv[]) 279 | { 280 | if(PIN_Init(argc, argv)){ 281 | return Usage(); 282 | } 283 | 284 | PIN_SetSyntaxIntel(); 285 | PIN_AddSyscallEntryFunction(Syscall_entry, 0); 286 | INS_AddInstrumentFunction(Instruction, 0); 287 | PIN_StartProgram(); 288 | 289 | return 0; 290 | } 291 | 292 | -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintInMemoryAndRegisters/crackme: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/TaintAnalysis/SpreadTheTaintInMemoryAndRegisters/crackme -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintInMemoryAndRegisters/crackme.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Jonathan Salwan - Copyright (C) 2013-07 3 | ** 4 | ** http://twitter.com/JonathanSalwan 5 | ** http://shell-storm.org 6 | ** 7 | ** This program is free software: you can redistribute it and/or modify 8 | ** it under the terms of the GNU General Public License as published by 9 | ** the Free Software Foundation, either version 3 of the License, or 10 | ** (at your option) any later version. 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | char *serial = "\x30\x39\x3c\x21\x30"; 19 | 20 | int main(void) 21 | { 22 | int fd, i = 0; 23 | char *buf; 24 | char *r; 25 | 26 | buf = malloc(256); 27 | if (!buf) 28 | return -1; 29 | r = buf; 30 | fd = open("serial.txt", O_RDONLY); 31 | read(fd, buf, 256); 32 | close(fd); 33 | while (i < 5){ 34 | if ((*buf ^ 0x55) != *serial) 35 | return 0; 36 | buf++, serial++, i++; 37 | } 38 | if (!*buf) 39 | printf("Good boy\n"); 40 | free(r); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintInMemoryAndRegisters/file.txt: -------------------------------------------------------------------------------- 1 | skdjsakhdjsahdjsahdjsadhjsakhd 2 | -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintInMemoryAndRegisters/makefile: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # DO NOT EDIT THIS FILE! 4 | # 5 | ############################################################## 6 | 7 | # If the tool is built out of the kit, PIN_ROOT must be specified in the make invocation and point to the kit root. 8 | ifdef PIN_ROOT 9 | CONFIG_ROOT := $(PIN_ROOT)/source/tools/Config 10 | else 11 | CONFIG_ROOT := ../Config 12 | endif 13 | include $(CONFIG_ROOT)/makefile.config 14 | include makefile.rules 15 | include $(TOOLS_ROOT)/Config/makefile.default.rules 16 | 17 | ############################################################## 18 | # 19 | # DO NOT EDIT THIS FILE! 20 | # 21 | ############################################################## 22 | -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintInMemoryAndRegisters/makefile.rules: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # This file includes all the test targets as well as all the 4 | # non-default build rules and test recipes. 5 | # 6 | ############################################################## 7 | 8 | 9 | ############################################################## 10 | # 11 | # Test targets 12 | # 13 | ############################################################## 14 | 15 | ###### Place all generic definitions here ###### 16 | 17 | # This defines tests which run tools of the same name. This is simply for convenience to avoid 18 | # defining the test name twice (once in TOOL_ROOTS and again in TEST_ROOTS). 19 | # Tests defined here should not be defined in TOOL_ROOTS and TEST_ROOTS. 20 | TEST_TOOL_ROOTS := Taint 21 | 22 | # This defines the tests to be run that were not already defined in TEST_TOOL_ROOTS. 23 | TEST_ROOTS := 24 | 25 | # This defines a list of tests that should run in the "short" sanity. Tests in this list must also 26 | # appear either in the TEST_TOOL_ROOTS or the TEST_ROOTS list. 27 | # If the entire directory should be tested in sanity, assign TEST_TOOL_ROOTS and TEST_ROOTS to the 28 | # SANITY_SUBSET variable in the tests section below (see example in makefile.rules.tmpl). 29 | SANITY_SUBSET := 30 | 31 | # This defines the tools which will be run during the the tests, and were not already defined in 32 | # TEST_TOOL_ROOTS. 33 | TOOL_ROOTS := 34 | 35 | # This defines the static analysis tools which will be run during the the tests. They should not 36 | # be defined in TEST_TOOL_ROOTS. If a test with the same name exists, it should be defined in 37 | # TEST_ROOTS. 38 | # Note: Static analysis tools are in fact executables linked with the Pin Static Analysis Library. 39 | # This library provides a subset of the Pin APIs which allows the tool to perform static analysis 40 | # of an application or dll. Pin itself is not used when this tool runs. 41 | SA_TOOL_ROOTS := 42 | 43 | # This defines all the applications that will be run during the tests. 44 | APP_ROOTS := 45 | 46 | # This defines any additional object files that need to be compiled. 47 | OBJECT_ROOTS := 48 | 49 | # This defines any additional dlls (shared objects), other than the pintools, that need to be compiled. 50 | DLL_ROOTS := 51 | 52 | # This defines any static libraries (archives), that need to be built. 53 | LIB_ROOTS := 54 | 55 | 56 | ############################################################## 57 | # 58 | # Test recipes 59 | # 60 | ############################################################## 61 | 62 | # This section contains recipes for tests other than the default. 63 | # See makefile.default.rules for the default test rules. 64 | # All tests in this section should adhere to the naming convention: .test 65 | 66 | 67 | ############################################################## 68 | # 69 | # Build rules 70 | # 71 | ############################################################## 72 | 73 | # This section contains the build rules for all binaries that have special build rules. 74 | # See makefile.default.rules for the default build rules. 75 | -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintInMemoryAndRegisters/pin.log: -------------------------------------------------------------------------------- 1 | Pin 2.12 kit 58423 2 | E: Taint.cpp:238: Invalid REG for IARG_REG_VALUE reg: xmm0 3 | -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintInMemoryAndRegisters/pintool.log: -------------------------------------------------------------------------------- 1 | Pin 2.12 kit 58423 2 | A: Source/pin/core_ia32/operand_ia32.cpp:INS_OperandIsReg:INS_OperandIsReg:356: assertion failed: n < xed_inst_noperands(xedi) 3 | 4 | -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintInMemoryAndRegisters/serial.txt: -------------------------------------------------------------------------------- 1 | elite -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintInMemoryAndRegisters/test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/TaintAnalysis/SpreadTheTaintInMemoryAndRegisters/test -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintInMemoryAndRegisters/test.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define true 0 9 | #define false !true 10 | 11 | int foo2(char a, char b, char c) 12 | { 13 | a = 1; 14 | b = 2; 15 | c = 3; 16 | 17 | return 0; 18 | } 19 | 20 | int foo(char *buf) 21 | { 22 | char c; 23 | char b; 24 | char a; 25 | 26 | c = buf[0]; 27 | b = c; 28 | a = buf[8]; 29 | 30 | foo2(a, b, c); 31 | 32 | return true; 33 | } 34 | 35 | int main(int ac, char **av) 36 | { 37 | int fd; 38 | char *buf; 39 | 40 | if (!(buf = malloc(32))) 41 | return -1; 42 | 43 | fd = open("./file.txt", O_RDONLY); 44 | read(fd, buf, 32), close(fd); 45 | foo(buf); 46 | } 47 | -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintInMemoryAndRegisters/test2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/TaintAnalysis/SpreadTheTaintInMemoryAndRegisters/test2 -------------------------------------------------------------------------------- /TaintAnalysis/SpreadTheTaintInMemoryAndRegisters/test2.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define true 0 9 | #define false !true 10 | 11 | int foo(char *buf) 12 | { 13 | if (buf[0] != 't') 14 | return false; 15 | if (buf[0] != 'e') 16 | return false; 17 | if (buf[0] != 's') 18 | return false; 19 | if (buf[0] != 't') 20 | return false; 21 | 22 | return true; 23 | } 24 | 25 | int main(int ac, char **av) 26 | { 27 | int fd; 28 | char *buf; 29 | 30 | if (!(buf = malloc(32))) 31 | return -1; 32 | 33 | fd = open("./file.txt", O_RDONLY); 34 | read(fd, buf, 32), close(fd); 35 | foo(buf); 36 | } 37 | -------------------------------------------------------------------------------- /Talks/SSTIC-2015/SSTIC_2015_detailed_version_Triton_Concolic_Execution_FrameWork_FSaudel_JSalwan.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/Talks/SSTIC-2015/SSTIC_2015_detailed_version_Triton_Concolic_Execution_FrameWork_FSaudel_JSalwan.pdf -------------------------------------------------------------------------------- /Talks/SSTIC-2015/SSTIC_2015_light_version_Triton_Concolic_Execution_FrameWork_FSaudel_JSalwan.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/Talks/SSTIC-2015/SSTIC_2015_light_version_Triton_Concolic_Execution_FrameWork_FSaudel_JSalwan.pdf -------------------------------------------------------------------------------- /Talks/SecurityDayLille-2015/README.rst: -------------------------------------------------------------------------------- 1 | Dynamic Binary Analysis and Instrumentation Covering a function using a DSE approach 2 | ==================================================================================== 3 | 4 | **Abstract**: This talk is about binary analysis and instrumentation. We will see how it's 5 | possible to target a specific function, snapshot the context memory/registers before the 6 | function, translate the instrumentation into an intermediate representation,apply a taint 7 | analysis based on this IR, build/keep formulas for a Dynamic Symbolic Execution (DSE), 8 | generate a concrete value to go through a specific path, restore the context memory/register 9 | and generate another concrete value to go through another path then repeat this operation 10 | until the target function is covered. 11 | 12 | 13 | -------------------------------------------------------------------------------- /Talks/SecurityDayLille-2015/SecurityDay2015_dynamic_symbolic_execution_Jonathan_Salwan.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/Talks/SecurityDayLille-2015/SecurityDay2015_dynamic_symbolic_execution_Jonathan_Salwan.pdf -------------------------------------------------------------------------------- /Talks/StHack-2015/README.rst: -------------------------------------------------------------------------------- 1 | Dynamic Behavior Analysis Using Binary Instrumentation 2 | ======================================================= 3 | 4 | **Abstract**: This talk can be considered like the part 2 of my talk at SecurityDay. In the 5 | previous part, I talked about how it was possible to cover a targeted function in memory 6 | using the DSE (Dynamic Symbolic Execution) approach. Cover a function (or its states) 7 | doesn't mean find all vulnerabilities, some vulnerability doesn't crashes the program. 8 | That's why we must implement specific analysis to find specific bugs. These analysis are 9 | based on the binary instrumentation and the runtime behavior analysis of the program. In 10 | this talk, we will see how it's possible to find these following kind of bugs : off-by-one, 11 | stack / heap overflow, use-after-free, format string and {write, read}-what-where. 12 | 13 | -------------------------------------------------------------------------------- /Talks/StHack-2015/StHack2015_Dynamic_Behavior_Analysis_using_Binary_Instrumentation_Jonathan_Salwan.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonathanSalwan/PinTools/55e69218a03368a7d516beec7f2673b681e8173b/Talks/StHack-2015/StHack2015_Dynamic_Behavior_Analysis_using_Binary_Instrumentation_Jonathan_Salwan.pdf --------------------------------------------------------------------------------