66import logging
77import shutil
88from functools import wraps
9- import tempfile
109import random
1110import unittest
1211
1312import claripy
1413
1514import patcherex
16- from patcherex .patch_master import PatchMaster
1715from patcherex .backends .detourbackend import DetourBackend
1816from patcherex .backends .reassembler_backend import ReassemblerBackend
1917from patcherex .patches import *
@@ -123,8 +121,7 @@ def wrapper():
123121 f (DetourBackend , None , True )
124122 return wrapper
125123
126- @add_fallback_strategy
127- def test_shadowstack (BackendClass , data_fallback , try_pdf_removal ):
124+ def _test_shadowstack (BackendClass , data_fallback , try_pdf_removal ):
128125 filepath = os .path .join (bin_location , "CADET_00003" )
129126 pipe = subprocess .PIPE
130127
@@ -147,8 +144,11 @@ def test_shadowstack(BackendClass, data_fallback, try_pdf_removal):
147144 assert p .returncode == 68
148145
149146
150- @add_fallback_strategy
151- def test_packer (BackendClass , data_fallback , try_pdf_removal ):
147+ def test_shadowstack ():
148+ add_fallback_strategy (_test_shadowstack )
149+
150+
151+ def _test_packer (BackendClass , data_fallback , try_pdf_removal ):
152152 filepath = os .path .join (bin_location , "CADET_00003" )
153153 pipe = subprocess .PIPE
154154
@@ -167,8 +167,11 @@ def test_packer(BackendClass, data_fallback, try_pdf_removal):
167167 assert res [0 ] == expected and p .returncode == 0
168168
169169
170- @add_fallback_strategy
171- def test_simplecfi (BackendClass , data_fallback , try_pdf_removal ):
170+ def test_packer ():
171+ add_fallback_strategy (_test_packer )
172+
173+
174+ def _test_simplecfi (BackendClass , data_fallback , try_pdf_removal ):
172175 filepath = os .path .join (bin_location , "0b32aa01_01_2" )
173176 pipe = subprocess .PIPE
174177
@@ -207,8 +210,11 @@ def test_simplecfi(BackendClass, data_fallback, try_pdf_removal):
207210 assert res [0 ] == expected3 and p .returncode == 0x45
208211
209212
210- @add_fallback_strategy
211- def test_qemudetection (BackendClass , data_fallback , try_pdf_removal ):
213+ def test_simplecfi ():
214+ add_fallback_strategy (_test_simplecfi )
215+
216+
217+ def _test_qemudetection (BackendClass , data_fallback , try_pdf_removal ):
212218 filepath = os .path .join (bin_location , "0b32aa01_01_2" )
213219 pipe = subprocess .PIPE
214220
@@ -237,8 +243,11 @@ def test_qemudetection(BackendClass, data_fallback, try_pdf_removal):
237243 assert res [0 ] == expected and p .returncode == 0
238244
239245
240- @add_fallback_strategy
241- def test_randomsyscallloop (BackendClass , data_fallback , try_pdf_removal ):
246+ def test_qemudetection ():
247+ add_fallback_strategy (_test_qemudetection )
248+
249+
250+ def _test_randomsyscallloop (BackendClass , data_fallback , try_pdf_removal ):
242251 filepath = os .path .join (bin_location , "CADET_00003" )
243252 pipe = subprocess .PIPE
244253
@@ -262,8 +271,11 @@ def test_randomsyscallloop(BackendClass, data_fallback, try_pdf_removal):
262271 assert p .returncode == - 11
263272
264273
265- @add_fallback_strategy
266- def test_cpuid (BackendClass , data_fallback , try_pdf_removal ):
274+ def test_randomsyscallloop ():
275+ add_fallback_strategy (_test_randomsyscallloop )
276+
277+
278+ def _test_cpuid (BackendClass , data_fallback , try_pdf_removal ):
267279 filepath = os .path .join (bin_location , "CADET_00003" )
268280 pipe = subprocess .PIPE
269281
@@ -288,8 +300,11 @@ def test_cpuid(BackendClass, data_fallback, try_pdf_removal):
288300 assert p .returncode == - 11
289301
290302
291- @reassembler_only
292- def test_stackretencryption (BackendClass , data_fallback , try_pdf_removal ):
303+ def test_cpuid ():
304+ add_fallback_strategy (_test_cpuid )
305+
306+
307+ def _test_stackretencryption (BackendClass , data_fallback , try_pdf_removal ):
293308 filepath1 = os .path .join (bin_location , "0b32aa01_01_2" )
294309 filepath2 = os .path .join (bin_location , "CROMU_00070" )
295310 filepath3 = os .path .join (bin_location , "original/CROMU_00008" )
@@ -421,8 +436,11 @@ def test_stackretencryption(BackendClass, data_fallback, try_pdf_removal):
421436 '''
422437
423438
424- @reassembler_only
425- def test_indirectcfi (BackendClass , data_fallback , try_pdf_removal ):
439+ def test_stackretencryption ():
440+ reassembler_only (_test_stackretencryption )
441+
442+
443+ def _test_indirectcfi (BackendClass , data_fallback , try_pdf_removal ):
426444 tests = [
427445 ("patchrex/indirect_call_test_O0" , b"b7fff000" ),
428446 #("patchrex/indirect_call_test_fullmem_O0", b"78000000"),
@@ -647,6 +665,10 @@ def test_indirectcfi(BackendClass, data_fallback, try_pdf_removal):
647665 '''
648666
649667
668+ def test_indirectcfi ():
669+ reassembler_only (_test_indirectcfi )
670+
671+
650672def test_freeregs ():
651673 def bin_str (name ,btype = "original" ):
652674 return "%s/%s" % (btype ,name )
@@ -684,8 +706,7 @@ def bin_str(name,btype="original"):
684706 #import IPython; IPython.embed()
685707
686708
687- @reassembler_only
688- def test_transmitprotection (BackendClass , data_fallback , try_pdf_removal ):
709+ def _test_transmitprotection (BackendClass , data_fallback , try_pdf_removal ):
689710 def check_test (test ):
690711 values ,expected_crash = test
691712 tinput = b"08048000\n 00000005\n "
@@ -794,8 +815,6 @@ def check_test(test):
794815 ([(i ,1 ) for i in range (100 ,150 ,2 )]+ [(0 ,3 )]+ [(i ,1 ) for i in range (100 ,150 ,2 )]+ [(10 ,3 )]+ [(13 ,1 )],True ),
795816 ([(i ,1 ) for i in range (100 ,150 ,2 )]+ [(0 ,3 )]+ [(i ,1 ) for i in range (100 ,150 ,2 )]+ \
796817 [(1000 ,1 )]+ [(10 ,3 )]+ [(13 ,1 )],True ),
797- ([(i ,1 ) for i in range (100 ,150 ,2 )]+ [(0 ,3 )]+ [(i ,1 ) for i in range (100 ,150 ,2 )]+ \
798- [(1000 ,1 )]+ [(10 ,3 )]+ [(13 ,1 )]+ [(i ,3 ) for i in range (1000 ,1100 ,4 )]+ [(2000 ,3 )],True ),
799818 ([(i ,1 ) for i in range (100 ,150 ,2 )]+ [(0 ,3 )]+ [(i ,1 ) for i in range (100 ,150 ,2 )]+ \
800819 [(1000 ,1 )]+ [(10 ,2 )]+ [(13 ,1 )]+ [(i ,3 ) for i in range (1000 ,1100 ,4 )]+ [(2000 ,3 )],False )
801820 ]
@@ -804,8 +823,11 @@ def check_test(test):
804823 check_test (test )
805824
806825
807- @reassembler_only
808- def test_shiftstack (BackendClass , data_fallback , try_pdf_removal ):
826+ def test_transmitprotection ():
827+ reassembler_only (_test_transmitprotection )
828+
829+
830+ def _test_shiftstack (BackendClass , data_fallback , try_pdf_removal ):
809831 filepath = os .path .join (bin_location , "CROMU_00044" )
810832 tinput = b"1\n " * 50 + b"2\n " * 50
811833
@@ -858,9 +880,11 @@ def test_shiftstack(BackendClass, data_fallback, try_pdf_removal):
858880 print (map (hex ,random_stack_pos ))
859881 assert len (random_stack_pos )>= 2
860882
883+ def test_shiftstack ():
884+ reassembler_only (_test_shiftstack )
885+
861886
862- @try_reassembler_and_detour_full # this changes the headers, let't test it in all 4 cases
863- def test_nxstack (BackendClass , data_fallback , try_pdf_removal ):
887+ def _test_nxstack (BackendClass , data_fallback , try_pdf_removal ):
864888 filepath = os .path .join (bin_location , "CROMU_00044" )
865889 tinput = b"login\n " * 50 + b"2\n " * 50
866890 res = QEMURunner (filepath ,tinput ,record_stdout = True )
@@ -968,8 +992,12 @@ def test_nxstack(BackendClass, data_fallback, try_pdf_removal):
968992 '''
969993
970994
971- @try_reassembler_and_detour
972- def test_adversarial (BackendClass , data_fallback , try_pdf_removal ):
995+ def test_nxstack ():
996+ # this changes the headers, let's test it in all 4 cases
997+ try_reassembler_and_detour_full (_test_nxstack )
998+
999+
1000+ def _test_adversarial (BackendClass , data_fallback , try_pdf_removal ):
9731001 pipe = subprocess .PIPE
9741002 tinput = b"1\n " * 50 + b"2\n " * 50
9751003 filepath = os .path .join (bin_location , "CROMU_00044" )
@@ -994,8 +1022,11 @@ def test_adversarial(BackendClass, data_fallback, try_pdf_removal):
9941022 assert original_res [1 ] != patched_res [1 ]
9951023
9961024
997- @reassembler_only
998- def test_backdoor (BackendClass , data_fallback , try_pdf_removal ):
1025+ def test_adversarial ():
1026+ try_reassembler_and_detour_full (_test_adversarial )
1027+
1028+
1029+ def _test_backdoor (BackendClass , data_fallback , try_pdf_removal ):
9991030 def solution_to_bytearray (l ):
10001031 # deal with endianness craziness
10011032 return bytes ([ l [3 ],l [2 ],l [1 ],l [0 ],0 ,0 ,0 ,l [4 ] ])
@@ -1104,8 +1135,11 @@ def solution_to_bytearray(l):
11041135 '''
11051136
11061137
1107- @reassembler_only
1108- def test_bitflip (BackendClass , data_fallback , try_pdf_removal ):
1138+ def test_backdoor ():
1139+ reassembler_only (_test_backdoor )
1140+
1141+
1142+ def _test_bitflip (BackendClass , data_fallback , try_pdf_removal ):
11091143 all_chars = [bytes ([c ]) for c in range (256 )]
11101144 pipe = subprocess .PIPE
11111145 tests = []
@@ -1162,8 +1196,10 @@ def test_bitflip(BackendClass, data_fallback, try_pdf_removal):
11621196 print (test , tlen )
11631197 assert expected == patched
11641198
1165- @reassembler_only
1166- def test_uninitialized (BackendClass , data_fallback , try_pdf_removal ):
1199+ def test_bitflip ():
1200+ reassembler_only (_test_bitflip )
1201+
1202+ def _test_uninitialized (BackendClass , data_fallback , try_pdf_removal ):
11671203 filepath = os .path .join (bin_location , "CROMU_00070" )
11681204
11691205 with patcherex .utils .tempdir () as td :
@@ -1204,8 +1240,12 @@ def test_uninitialized(BackendClass, data_fallback, try_pdf_removal):
12041240 res = p .communicate (poll_input )
12051241 assert expected_output == res [0 ]
12061242
1207- @reassembler_only
1208- def test_malloc_patcher (BackendClass , data_fallback , try_pdf_removal ):
1243+
1244+ def test_uninitialized ():
1245+ reassembler_only (_test_uninitialized )
1246+
1247+
1248+ def _test_malloc_patcher (BackendClass , data_fallback , try_pdf_removal ):
12091249 filepath = os .path .join (bin_location , "NRFIN_00078" )
12101250
12111251 with patcherex .utils .tempdir () as td :
@@ -1239,6 +1279,10 @@ def test_malloc_patcher(BackendClass, data_fallback, try_pdf_removal):
12391279 '''
12401280
12411281
1282+ def test_malloc_patcher ():
1283+ @reassembler_only (_test_malloc_patcher )
1284+
1285+
12421286@reassembler_only
12431287def disable_no_flag_printf (BackendClass , data_fallback , try_pdf_removal ):
12441288
@@ -1304,8 +1348,8 @@ def disable_no_flag_printf(BackendClass, data_fallback, try_pdf_removal):
13041348 assert expected_stdout == actual_stdout
13051349 '''
13061350
1307- @ detour_only
1308- def test_countdown_1 (BackendClass , data_fallback , try_pdf_removal ):
1351+
1352+ def _test_countdown_1 (BackendClass , data_fallback , try_pdf_removal ):
13091353 filepath = os .path .join (bin_location , "countdown_test" )
13101354
13111355 with patcherex .utils .tempdir () as td :
@@ -1329,8 +1373,7 @@ def test_countdown_1(BackendClass, data_fallback, try_pdf_removal):
13291373 assert expected_output == res [0 ]
13301374
13311375
1332- @detour_only
1333- def test_countdown_2 (BackendClass , data_fallback , try_pdf_removal ):
1376+ def _test_countdown_2 (BackendClass , data_fallback , try_pdf_removal ):
13341377 filepath = os .path .join (bin_location , "countdown_test" )
13351378
13361379 with patcherex .utils .tempdir () as td :
@@ -1351,32 +1394,36 @@ def test_countdown_2(BackendClass, data_fallback, try_pdf_removal):
13511394 res = p .communicate (b"foo\n " )
13521395 assert expected_output == res [0 ]
13531396
1397+ def test_countdown_2 ():
1398+ reassembler_only (_test_countdown_2 )
1399+
13541400
1355- @detour_only
1356- def test_countdown_3 (BackendClass , data_fallback , try_pdf_removal ):
1401+ def _test_countdown_3 (BackendClass , data_fallback , try_pdf_removal ):
13571402 filepath = os .path .join (bin_location , "countdown_test" )
13581403
13591404 with patcherex .utils .tempdir () as td :
13601405 tmp_file = os .path .join (td , "patched" )
13611406 backend = BackendClass (filepath , try_pdf_removal = try_pdf_removal )
13621407 obj = backend .project .loader .main_object
13631408 patch_list = []
1364- patch_list .append ({"target_addr" : obj .offset_to_addr (0x0a42 ), "dst_active" : obj .offset_to_addr (0x0a6e ), "dst_zero" : obj .offset_to_addr (0x0a49 ), "num_instr" : 3 , "extra_code" : "movzx eax, byte [rax]\n cmp al, 0x2d" , "extra_is_c" : False })
1365- patch_list .append ({"target_addr" : obj .offset_to_addr (0x0b32 ), "dst_active" : obj .offset_to_addr (0x0a6e ), "dst_zero" : Countdown .ZERO_TARGET_EXIT , "num_instr" : 1 ,})
1366- patch_list .append ({"target_addr" : obj .offset_to_addr (0x0b2c ), "dst_active" : obj .offset_to_addr (0x0a6e ), "dst_zero" : Countdown .ZERO_TARGET_EXIT , "num_instr" : 1 })
1409+ patch_list .append ({"target_addr" : obj .offset_to_addr (0x09d5 ), "dst_active" : obj .offset_to_addr (0x09ee ), "dst_zero" : obj .offset_to_addr (0x09db ), "num_instr" : 2 , "extra_code" : "cmp dword [rbp - 4], 3" , "extra_is_c" : False })
13671410 cp = Countdown (filepath , backend , patch_list = patch_list , count = 2 )
13681411 patches = cp .get_patches ()
13691412 backend .apply_patches (patches )
13701413 backend .save (tmp_file )
13711414
1372- # We should only see the prompt twice
1373- expected_output = b"$> foo\n Wrong length !\n \n $> test \n Unkown command! \n \n "
1415+ # We should not see the "Wrong length" error
1416+ expected_output = b"$> foo\n Unkown command !\n \n $> "
13741417 pipe = subprocess .PIPE
13751418 p = subprocess .Popen ([tmp_file , "-run" ], stdin = pipe , stdout = pipe , stderr = pipe )
1376- res = p .communicate (b"foo\n test \ n " )
1419+ res = p .communicate (b"foo\n " )
13771420 assert expected_output == res [0 ]
13781421
13791422
1423+ def test_countdown_3 ():
1424+ detour_only (_test_countdown_3 )
1425+
1426+
13801427def run_all ():
13811428 functions = globals ()
13821429 all_functions = dict (filter ((lambda x : x [0 ].startswith ('test_' )), functions .items ()))
0 commit comments