21.03.2013 Views

Problem - Kevin Tafuro

Problem - Kevin Tafuro

Problem - Kevin Tafuro

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

*/<br />

printf("CRC is %08X\n", crc);<br />

#else<br />

if (crc != crc32_stored) {<br />

printf("CRC32 %#08X does not match %#08X\n", crc, crc32_stored);<br />

return 1;<br />

}<br />

printf("CRC32 %#08X is OK\n", crc);<br />

#endif<br />

return 0;<br />

}<br />

As mentioned in the comment just prior to the printf( ) call in main( ), you should<br />

compile this program with TEST_BUILD defined, then execute it to obtain the CRC<br />

value that needs to be replaced for crc32_stored in the binary. Then rebuild the program<br />

with TEST_BUILD undefined, and modify the binary with the proper CRC value<br />

from the first run.<br />

It is tempting to generate a checksum of the entire program and use this to determine<br />

whether any bytes have been changed; however, this causes a loss of granularity<br />

for the checksum and can degrade performance. Instead, you should generate<br />

multiple checksums for vital sections of code. These checksums can be encrypted,<br />

and they can even be supplemented with checksums of trivial blocks of code to disguise<br />

which portions of code are significant.<br />

The check used in main( ) performs a simple comparison, if (crc != crc32_stored).<br />

While this demonstrates the basic use of a checksum, use of a straight comparison<br />

such as this is strongly discouraged. When disassembled, the call to crc32( ) and the<br />

subsequent compare are immediately obvious:<br />

804842b: ff 75 fc pushl -4(%ebp)<br />

804842e: ff 75 f8 pushl -8(%ebp)<br />

8048431: e8 f2 fe ff ff call 8048328 ;call crc32( )<br />

8048436: 83 c4 10 add $0x10,%esp<br />

8048439: 89 45 f4 mov %eax,-12(%ebp)<br />

804843c: 8b 45 f4 mov -12(%ebp),%eax<br />

804843f: 3b 05 d0 83 04 08 cmp 0x80483d0,%eax ;compare result<br />

8048445: 74 22 je 8048469 ;jump-if-equal<br />

An attacker simply has to change the je instruction (opcode 0x74) at offset 8048445<br />

to a jmp instruction (opcode 0xEB) to defeat this protection. The generated checksum<br />

should never be checked against a valid one; instead, the generated checksum should<br />

be used as a source of information that the program requires to execute properly. A<br />

byte within the checksum could be used as an index into a jump table, for example,<br />

or the checksum itself could be used as a key to decrypt critical code or data.<br />

The next program demonstrates how to use a table of function pointers to test the<br />

value of a checksum. Each nibble or half-byte in the checksum is used as an index<br />

into a 16-entry table of function pointers; only the correct table entry calls the function<br />

to check the next nibble. This method requires 8 tables of 16 function pointers<br />

so that one table is used for each nibble in the checksum.<br />

656 | Chapter 12: Anti-Tampering<br />

This is the Title of the Book, eMatter Edition<br />

Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!