赛题出的很有水平啊,第一天出去玩了一天,第二天才开始做,只做出了这么几题,看了一下firmware是个虚拟机,再多点时间应该也可以出
侧防 这题比较简单,放在了,没有放在re分类,直接上脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 byte_4010 = [0x51 , 0x57 , 0x42 , 0x6C , 0x6F , 0x67 , 0x73 ] target = "Lx|dTUwe\\IvNhCBOLqDNfW}ImFZCtiyxO\\PW^ebD" f = [] for i in range (0 , len (target), 4 ): f.append(target[i + 1 ]) f.append(target[i + 2 ]) f.append(target[i + 3 ]) f.append(target[i]) flag = "" for i, c in enumerate (f): flag += chr ((ord (c) - 65 ) ^ byte_4010[i % 7 ]) print (flag)
xx_warmup_obf 混淆+花指令+反调,从read或者strlen函数开始找起会比较方便,找到之后发现一位一位计算,为了节省时间,代码跑出一部分之后后面的flag可以直接猜出来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 from z3 import *def RecurOr (flags, models, pos=0 ): if pos <= len (flags) - 1 : return Or(models[flags[pos]] != flags[pos], RecurOr(flags, models, pos + 1 )) else : return Or(models[flags[pos]] != flags[pos]) f = [BitVec('v%d' % i, 16 ) for i in range (22 )] flag = [] solver = Solver() for c in f: solver.add(c >= 0x0 ) solver.add(c <= 0xff ) solver.add(f[0 ] == ord ('f' )) solver.add(f[1 ] == ord ('l' )) solver.add(f[2 ] == ord ('a' )) solver.add(f[3 ] == ord ('g' )) solver.add(f[4 ] == ord ('{' )) solver.add((f[5 ] * 0x1eb9d + f[2 ] * 0x40a8c + f[3 ] * 0x3fb3f + f[4 ] * 0xfffb82cd + f[1 ] * 0xffffea88 + f[0 ] * 0xfffda7c3 ) & 0xffffffff == 0xc78321 ) solver.add((f[6 ] * 0xfffd185d + f[5 ] * 0xfffe032d + f[2 ] * 0xfffc468a + f[3 ] * 0xFFFC0EA3 + f[4 ] * 0xFFFE5277 + f[1 ] * 0xfffc4328 + f[0 ] * 0x44DE ) & 0xffffffff == 0xF961DAEB ) solver.add((f[6 ] * 0x35770 + f[5 ] * 0x1CC39 + f[2 ] * 0x4851 + f[3 ] * 0xFFFFE5B9 + f[4 ] * 0x36D92 + f[1 ] * 0xFFFCF9E1 + f[0 ] * 0x37C38 + f[7 ] * 0x4186D )& 0xffffffff == 0x4B202E4 ) solver.add((f[6 ] * 0xFFFC4AB1 + f[5 ] * 0x0CB64 + f[2 ] * 0x1309E + f[3 ] * 0xFFFB995E + f[4 ] * 0x2E940 + f[1 ] * 0xFFFEB612 + f[0 ] * 0xFFFC631A + f[7 ] * 0xFFFCAA83 + f[8 ] * 0x16A0C ) & 0xffffffff == 0xFCDE9AB5 ) solver.add((f[6 ] * 0x37EB9 + f[5 ] * 0xFFFDD238 + f[2 ] * 0xFFFBE2C0 + f[3 ] * 0x17977 + f[4 ] * 0x29D39 + f[1 ] * 0xFFFBB74E + f[0 ] * 0xFFFD6E33 + f[7 ] * 0xFFFF0427 + f[8 ] * 0xFFFD0153 + f[9 ] * 0xFFFF66A5 ) & 0xffffffff == 0xFBC7B90A ) solver.add((f[6 ] * 0x1DAAC + f[5 ] * 0xFFFE92AC + f[2 ] * 0xFFFF9AD4 + f[3 ] * 0x2C78D + f[4 ] * 0xFFFC69EE + f[1 ] * 0xFFFC1736 + f[0 ] * 0x47762 + f[7 ] * 0x28557 + f[8 ] * 0x27B6D + f[9 ] * 0xFFFF7F4E + f[10 ] * 0x2F9DF ) & 0xffffffff == 0x1AF43AB ) solver.add((f[6 ] * 0xFFFDFD46 + f[5 ] * 0xFFFBD6F6 + f[2 ] * 0x13A87 + f[3 ] * 0x42997 + f[4 ] * 0x244E9 + f[1 ] * 0x20A60 + f[0 ] * 0x0C3F6 + f[7 ] * 0xFFFC0F74 + f[8 ] * 0xFFFE4DC8 + f[9 ] * 0xFFFE94DC + f[10 ] * 0xFFFFECB4 + f[11 ] * 0xFFFD79C6 ) & 0xffffffff == 0xFEAFEC1F ) solver.add((f[6 ] * 0xFFFE7848 + f[5 ] * 0x23EE3 + f[2 ] * 0xFFFCBAB4 + f[3 ] * 0x27C92 + f[4 ] * 0xFFFBFD5C + f[1 ] * 0xFFFD30C3 + f[0 ] * 0x5009 + f[7 ] * 0xFFFE93F1 + f[8 ] * 0xFFFDE3F3 + f[9 ] * 0x228DC + f[10 ] * 0x25EE + f[11 ] * 0xF242 + f[12 ] * 0x1160E ) & 0xffffffff == 0xFE20EC14 ) solver.add((f[6 ] * 0x648B + f[5 ] * 0xFFFCF002 + f[2 ] * 0xFFFE2E15 + f[3 ] * 0x1E041 + f[4 ] * 0x594B + f[1 ] * 0xFFFF3713 + f[0 ] * 0xFFFED96C + f[7 ] * 0x1C620 + f[8 ] * 0xFFFF282A + f[9 ] * 0xFFFF0E48 + f[10 ] * 0xFFFEAC54 + f[11 ] * 0xEA5F + f[12 ] * 0x35CF4 + f[13 ] * 0xFFFC920E ) & 0xffffffff == 0xFDCA76A0 ) solver.add((f[6 ] * 0x107E1 + f[5 ] * 0x440D9 + f[2 ] * 0xFFFFF5C3 + f[3 ] * 0x30766 + f[4 ] * 0x21281 + f[1 ] * 0x235C2 + f[0 ] * 0x1B2CE + f[7 ] * 0x16687 + f[8 ] * 0x493EC + f[9 ] * 0x26716 + f[0xA ] * 0xFFFC84CB + f[0xB ] * 0xFFFEA6FA + f[0xC ] * 0xFFFC2F98 + f[0xD ] * 0xFFFD1A3E + f[0xE ] * 0x390BF ) & 0xffffffff == 0x5920B01 ) solver.add((f[6 ] * 0x24225 + f[5 ] * 0xFFFD39FC + f[2 ] * 0x1EAE2 + f[3 ] * 0x2F613 + f[4 ] * 0xFFFC66F9 + f[1 ] * 0xFFFE0433 + f[0 ] * 0x3E19 + f[7 ] * 0x1BDFF + f[8 ] * 0xFFFC6EAB + f[9 ] * 0xFFFD810C + f[0xA ] * 0x0D519 + f[0xB ] * 0x384EC + f[0xC ] * 0x197E5 + f[0xD ] * 0xFFFFD159 + f[0xE ] * 0xFFFF43D9 + f[0xF ] * 0xFFFC28DF ) & 0xffffffff == 0xFDD0E812 ) solver.add((f[6 ] * 0x111A3 + f[5 ] * 0xFFFF32EB + f[2 ] * 0x3E3F9 + f[3 ] * 0xFFFE9E4B + f[4 ] * 0xFFFFFB1A + f[1 ] * 0xFFFF65B9 + f[0 ] * 0xFFFDF970 + f[7 ] * 0xFFFB936C + f[8 ] * 0xFFFEF482 + f[9 ] * 0x57B6 + f[0xA ] * 0x8813 + f[0xB ] * 0x25CDC + f[0xC ] * 0x12190 + f[0xD ] * 0x427BE + f[0xE ] * 0xFFFC8358 + f[0xF ] * 0xFFFCE4EE + f[0x10 ] * 0x43BB5 ) & 0xffffffff == 0xFF9ADC73 ) solver.add((f[6 ] * 0xFFFC313D + f[5 ] * 0x1023B + f[2 ] * 0x2E27A + f[3 ] * 0xFFFDCCD4 + f[4 ] * 0xFFFE498F + f[1 ] * 0xFFFFEC0D + f[0 ] * 0x3A1A3 + f[7 ] * 0xFFFCC8E2 + f[8 ] * 0xFFFC37B6 + f[9 ] * 0xFFFF2FE9 + f[0xA ] * 0xFFFE8E68 + f[0xB ] * 0x1F45C + f[0xC ] * 0xFFFEAC48 + f[0xD ] * 0xFFFDBD08 + f[0xE ] * 0x2A28 + f[0xF ] * 0xD72D + f[0x10 ] * 0xFFFF70B8 + f[0x11 ] * 0xFFFFE90F ) & 0xffffffff == 0xFCD6008F ) solver.add((f[6 ] * 0xFFFBB7A0 + f[5 ] * 0xFFFF0015 + f[2 ] * 0xFFFD2918 + f[3 ] * 0x1882D + f[4 ] * 0xFFFEDE1F + f[1 ] * 0x2FB77 + f[0 ] * 0x20D94 + f[7 ] * 0x14A94 + f[8 ] * 0xFFFDA0CD + f[9 ] * 0xDE69 + f[0xA ] * 0x2FE8 + f[0xB ] * 0x2ABE5 + f[0xC ] * 0x26530 + f[0xD ] * 0x4C3D + f[0xE ] * 0x2383E + f[0xF ] * 0x42763 + f[0x10 ] * 0xE5C9 + f[0x11 ] * 0x539 + f[0x12 ] * 0xFFFC5AF3 ) & 0xffffffff == 0x39F3331 ) solver.add((f[6 ] * 0xFFFD67BD + f[5 ] * 0xFFFCFC61 + f[2 ] * 0x21FB1 + f[3 ] * 0x2AFE7 + f[4 ] * 0xFFFE2316 + f[1 ] * 0xFFFDE3DE + f[0 ] * 0xFFFCF431 + f[7 ] * 0xFFFF1A07 + f[8 ] * 0xFFFD1877 + f[9 ] * 0xFFFBAB46 + f[0xA ] * 0xFFFFB7A8 + f[0xB ] * 0x44C76 + f[0xC ] * 0x3C062 + f[0xD ] * 0x26DA8 + f[0xE ] * 0x217FE + f[0xF ] * 0x27911 + f[0x10 ] * 0xD484 + f[0x11 ] * 0x217F6 + f[0x12 ] * 0xFFFF711C + f[0x13 ] * 0xFFFE6835 ) & 0xffffffff == 0x4AF658 ) solver.add((f[6 ] * 0x6C67 + f[5 ] * 0x4210C + f[2 ] * 0x24372 + f[3 ] * 0xFFFF64A1 + f[4 ] * 0xFFFE83FC + f[1 ] * 0xFFFC59E3 + f[0 ] * 0x1A675 + f[7 ] * 0x29403 + f[8 ] * 0x122E6 + f[9 ] * 0x479E1 + f[0xA ] * 0xFFFE556B + f[0xB ] * 0xFFFEE2E8 + f[0xC ] * 0xFFFD0C98 + f[0xD ] * 0xF761 + f[0xE ] * 0xFFFCF4FD + f[0xF ] * 0x24A14 + f[0x10 ] * 0x2C39B + f[0x11 ] * 0xFFFF914F + f[0x12 ] * 0x94F9 + f[0x13 ] * 0x1F3A9 + f[0x14 ] * 0xFFFD85A7 ) & 0xffffffff == 0x2B77651 ) solver.add((f[6 ] * 0x0B245 + f[5 ] * 0x47951 + f[2 ] * 0x3C177 + f[3 ] * 0x2026C + f[4 ] * 0x2BD3A + f[1 ] * 0x0AE83 + f[0 ] * 0xFFFF67E2 + f[7 ] * 0x0FC81 + f[8 ] * 0xFFFD1DCD + f[9 ] * 0xFFFE7D87 + f[0xA ] * 0x40428 + f[0xB ] * 0x1AC25 + f[0xC ] * 0x47B95 + f[0xD ] * 0xFFFBD35D + f[0xE ] * 0xFFFD55C5 + f[0xF ] * 0x255EF + f[0x10 ] * 0xFFFCA285 + f[0x11 ] * 0x1B4F2 + f[0x12 ] * 0xFFFBA306 + f[0x13 ] * 0x3B929 + f[0x14 ] * 0xEC4C +f[0x15 ]*0xFFFCD49C ) & 0xffffffff == 0x49F26C9 ) while solver.check() == sat: flag = "" model = solver.model() for i in range (len (f)): flag += chr (model[f[i]].as_long()) print (flag) solver.add(RecurOr(f, model))
根据题目描述,先做这个热热身,做完这个再去做xx_segment_obf也不迟
,猜测flag为
1 flag {g0 _Fuck_xx_5 egm3 nt_0 bf}
提交成功
imitation_game 运行程序,首先输出flag提示,flag有两部分,先过第一部分才会运行第二部分的程序
调试程序,调试过程中发现AES的s-box,发现输入了明文之后在后面pad了32位\x1a,然后进行AES-CBC加密,密钥和iv还有最终运行的结果可以在内存里找到,直接解密
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 from Crypto.Cipher import AESfrom binascii import b2a_hex, a2b_hexdef add_to_16 (text ): if len (text.encode('utf-8' )) % 16 : add = 16 - (len (text.encode('utf-8' )) % 16 ) else : add = 0 text = text + ('\0' * add) return text.encode('utf-8' ) def encrypt (text ): key = b"\x3E\x2C\x25\x13\x18\xBE\xC3\x6B\xA1\x37\x24\x53\x03\x1E\x51\xEC" iv = b"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F" mode = AES.MODE_CBC text = add_to_16(text) cryptos = AES.new(key, mode, iv) cipher_text = cryptos.encrypt(text) return b2a_hex(cipher_text) def decrypt (text ): key = b"\x3E\x2C\x25\x13\x18\xBE\xC3\x6B\xA1\x37\x24\x53\x03\x1E\x51\xEC" iv = b"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F" mode = AES.MODE_CBC cryptos = AES.new(key, mode, iv) plain_text = cryptos.decrypt(a2b_hex(text)) return plain_text if __name__ == '__main__' : e = encrypt("6c8f1d78770fe672122478c6f9a150e8\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a" ) d = decrypt(b"9D7BA23CB1099A4841D16663D6AE3CAB87ED59C2D3DA2A05BA5129C15D426A9A0514DBBEAE838B6FD3594152344E39C566E1E3EC0618149F4EB770009077D8AE" ) print ("加密:" , e) print ("解密:" , d)
得到第一部分flag,进入第二部分,调用了game.bin文件,根据提示是一个chip8的模拟器,一共输入10位数,错误则提示dead
有了提示之后好做了很多,根据chip8的指令集解析一下game.bin文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 with open ('game.txt' , 'r+' ) as f: s = f.read() j = 0 for i in range (0 , len (s), 5 ): t = s[i:i + 4 ] print ("addr:" + hex (j + 0x200 ), end=" " ) j += 2 if t[0 ] == '0' : if t[1 ] == '0' and t[2 ] == 'e' : if t[3 ] == '1' : print ("clear screen" ) elif t[3 ] == 'f' : print ("Returns from a subroutine" ) else : print ("call program at addr: " + t[1 :]) else : print ("call program at addr: " + t[1 :]) elif t[0 ] == '1' : print ("jmp " + t[1 :]) elif t[0 ] == '2' : print ("call " + t[1 :]) elif t[0 ] == '3' : print ("Skips the next instruction if V" + t[1 ] + " equals " + t[2 :]) elif t[0 ] == '4' : print ("Skips the next instruction if V" + t[1 ] + " not equals " + t[2 :]) elif t[0 ] == '5' : print ("Skips the next instruction if V" + t[1 ] + " equals V" + t[2 ]) elif t[0 ] == '6' : print ("V" + t[1 ] + " = " + t[2 :]) elif t[0 ] == '7' : print ("V" + t[1 ] + " += " + t[2 :]) elif t[0 ] == '8' : VX = "V" + t[1 ] VY = "V" + t[2 ] if t[-1 ] == '0' : print (VX + " = " + VY) elif t[-1 ] == '1' : print (VX + " = " + VX + " | " + VY) elif t[-1 ] == '2' : print (VX + " = " + VX + " & " + VY) elif t[-1 ] == '3' : print (VX + " = " + VX + " ^ " + VY) elif t[-1 ] == '4' : print (VX + " += " + VY, " set VF=1 if VX>=255" ) elif t[-1 ] == '5' : print (VX + " -= " + VY, " set VF=0 if VX<=0" ) elif t[-1 ] == '6' : print (VX + " >>= 1" , " the last one to VF" ) elif t[-1 ] == '7' : print (VX + " = " + VY + " - " + VX, " set VF=0 if VX<0" ) elif t[-1 ] == 'e' : print (VX + " <<= 1" , " the first one to VF" ) else : print ("Invalid instruction: " + t) elif t[0 ] == '9' : print ("Skips the next instruction if V" + t[1 ] + " not equals V" + t[2 ]) elif t[0 ] == 'a' : print ("set I = " + t[1 :]) elif t[0 ] == 'b' : print ("jmp V0+" + t[1 :]) elif t[0 ] == 'c' : print ("V" + t[1 ] + "=rand()&" + t[2 :]) elif t[0 ] == 'd' : print ("display at (V" + t[1 ] + "," + "V" + t[2 ] + ") for " + t[3 ] + "rows" ) elif t[0 ] == 'e' : print ("something about buttons" ) elif t[0 ] == 'f' : if t[2 :] == '29' : print ("set I=" + "V" + t[1 ]) elif t[2 :] == "0a" : print ("set V" + t[1 ] + " = button pressed" ) elif t[2 :] == "55" : print ("store V0-V" + t[1 ] + " to addr start at I" ) elif t[2 :] == "65" : print ("store addr start at I to V0-V" + t[1 ]) elif t[2 :] == "33" : print ("set BCD(V" + t[1 ] + ")" ) else : print (t[2 :]) else : print ("Invalid instruction: " + t)
解析之后根据程序的运行流程看一下大概过程,读取按键在屏幕上指定位置显示出来,直到10位都读取完,然后进行一些判断,错误就会显示dead,正确直接退出程序,不会有显示。然后详细看一下程序
程序开始一个跳转从2ce开始,根据chip8内存的排布规律,可执行代码从200开始
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 addr :0 x2 ce Ve = 10 addr :0 x2 d0 set I=Veaddr :0 x2 d2 store V0 -Ve to addr start at Iaddr :0 x2 d4 Vf = 03 addr :0 x2 d6 Ve += Vf set VF=1 if VX>=255 addr :0 x2 d8 call 928 addr :0 x2 da V0 = Vfaddr :0 x2 dc V1 = 05 addr :0 x2 de V2 = 08 addr :0 x2 e0 V3 = V0 addr :0 x2 e2 set I=Veaddr :0 x2 e4 store V0 -Ve to addr start at Iaddr :0 x2 e6 Vf = 03 addr :0 x2 e8 Ve += Vf set VF=1 if VX>=255 addr :0 x2 ea V0 = V1 addr :0 x2 ec V1 = V2 addr :0 x2 ee V2 = V3 addr :0 x2 f0 call 938
首先是10个这样的过程用于输入和显示
其中928用于读取输入,记录按键信息
1 2 3 4 5 6 7 8 addr :0 x928 V0 = ffaddr :0 x92 a set V0 = button pressedaddr :0 x92 c Vf = 03 addr :0 x92 e Ve -= Vf set VF=0 if VX<=0 addr :0 x930 Vf = V0 addr :0 x932 set I=Veaddr :0 x934 store addr start at I to V0 -Veaddr :0 x936 Returns from a subroutine
938用于输出到显示屏上
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 addr :0 x938 V5 = V2 addr :0 x93 a V4 = V1 addr :0 x93 c V3 = V0 addr :0 x93 e V6 = 00 addr :0 x940 set BCD(V5 )addr :0 x942 store addr start at I to V0 -V2 addr :0 x944 set I=V5 addr :0 x946 display at (V3 ,V4 ) for 5 rowsaddr :0 x948 V6 = V6 | Vfaddr :0 x94 a Vf = 03 addr :0 x94 c Ve -= Vf set VF=0 if VX<0 addr :0 x94 e Vf = V6 addr :0 x950 set I=Veaddr :0 x952 store addr start at I to V0 -Veaddr :0 x954 Returns from a subroutine
经过10次这样的操作之后,显示屏上显示出10个输入的数,分别存储在寄存器V0到V9中,接下来对这些输入的数值进行处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 addr :0 x436 Va = Vfaddr :0 x438 Va = V0 addr :0 x43 a Vb = V0 addr :0 x43 c Vc = 02 addr :0 x43 e Vb += Vc set VF=1 if VX>=255 addr :0 x440 Va = Vbaddr :0 x442 V0 = Vaaddr :0 x444 Va = V1 addr :0 x446 Vb = V1 addr :0 x448 Vc = 01 addr :0 x44 a Vb += Vc set VF=1 if VX>=255 addr :0 x44 c Va = Vbaddr :0 x44 e V1 = Vaaddr :0 x450 Va = V2 addr :0 x452 Vb = V2 addr :0 x454 Vc = 01 addr :0 x456 Vb += Vc set VF=1 if VX>=255 addr :0 x458 Vc = 01 addr :0 x45 a Vb = Vb ^ Vcaddr :0 x45 c Va = Vbaddr :0 x45 e V2 = Vaaddr :0 x460 Va = V3 addr :0 x462 Vb = V3 addr :0 x464 Vc = 03 addr :0 x466 Vb += Vc set VF=1 if VX>=255 addr :0 x468 Va = Vbaddr :0 x46 a V3 = Vaaddr :0 x46 c Va = V4 addr :0 x46 e Vb = V4 addr :0 x470 Vc = 02 addr :0 x472 Vb += Vc set VF=1 if VX>=255 addr :0 x474 Va = Vbaddr :0 x476 V4 = Vaaddr :0 x478 Va = V5 addr :0 x47 a Vb = V5 addr :0 x47 c Vc = 02 addr :0 x47 e Vb = Vb ^ Vcaddr :0 x480 Vc = 01 addr :0 x482 Vb += Vc set VF=1 if VX>=255 addr :0 x484 Va = Vbaddr :0 x486 V5 = Vaaddr :0 x488 Va = V6 addr :0 x48 a Vb = V6 addr :0 x48 c Vc = V6 addr :0 x48 e Vb += Vc set VF=1 if VX>=255 addr :0 x490 Va = Vbaddr :0 x492 V6 = Vaaddr :0 x494 Va = V7 addr :0 x496 Vb = V7 addr :0 x498 Vc = 01 addr :0 x49 a Vb += Vc set VF=1 if VX>=255 addr :0 x49 c Va = Vbaddr :0 x49 e V7 = Vaaddr :0 x4 a0 Va = V8 addr :0 x4 a2 Vb = V8 addr :0 x4 a4 Vc = 01 addr :0 x4 a6 Vb = Vb ^ Vcaddr :0 x4 a8 Vc = 01 addr :0 x4 aa Vb += Vc set VF=1 if VX>=255 addr :0 x4 ac Va = Vbaddr :0 x4 ae V8 = Vaaddr :0 x4 b0 Va = V9 addr :0 x4 b2 Vb = V9 addr :0 x4 b4 Vc = 02 addr :0 x4 b6 Vb += Vc set VF=1 if VX>=255 addr :0 x4 b8 Va = Vbaddr :0 x4 ba V9 = Va
就是如下操作
1 2 3 4 5 6 7 8 9 10 f[0 ]+=2 f[1 ]+=1 f[2 ]=(f[2 ]+1 )^1 f[3 ]+=3 f[4 ]+=2 f[5 ]=(f[5 ]^2 )+1 f[6 ]=2 *f[6 ] f[7 ]+=1 f[8 ]=(f[8 ]^1 )+1 f[9 ]+=2
接下来是10个方程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 addr :0 x4 bc Va = 00 addr :0 x4 be Vb = Vaaddr :0 x4 c0 Vc = V0 addr :0 x4 c2 Vd = 01 addr :0 x4 c4 set I=Veaddr :0 x4 c6 store V0 -Ve to addr start at Iaddr :0 x4 c8 Vf = 03 addr :0 x4 ca Ve += Vf set VF=1 if VX>=255 addr :0 x4 cc V0 = Vcaddr :0 x4 ce V1 = Vdaddr :0 x4 d0 call 27 aaddr :0 x4 d2 Vc = Vfaddr :0 x4 d4 Vb += Vc set VF=1 if VX>=255 addr :0 x4 d6 Va = Vbaddr :0 x4 d8 Vb = Vaaddr :0 x4 da Vc = V1 addr :0 x4 dc Vd = 02 addr :0 x4 de set I=Veaddr :0 x4 e0 store V0 -Ve to addr start at Iaddr :0 x4 e2 Vf = 03 addr :0 x4 e4 Ve += Vf set VF=1 if VX>=255 addr :0 x4 e6 V0 = Vcaddr :0 x4 e8 V1 = Vdaddr :0 x4 ea call 27 aaddr :0 x4 ec Vc = Vfaddr :0 x4 ee Vb += Vc set VF=1 if VX>=255 addr :0 x4 f0 Va = Vbaddr :0 x4 f2 Vb = Vaaddr :0 x4 f4 Vc = V2 addr :0 x4 f6 Vd = 01 addr :0 x4 f8 set I=Veaddr :0 x4 fa store V0 -Ve to addr start at Iaddr :0 x4 fc Vf = 03 addr :0 x4 fe Ve += Vf set VF=1 if VX>=255 addr :0 x500 V0 = Vcaddr :0 x502 V1 = Vdaddr :0 x504 call 27 aaddr :0 x506 Vc = Vfaddr :0 x508 Vb += Vc set VF=1 if VX>=255 addr :0 x50 a Va = Vbaddr :0 x50 c Vb = Vaaddr :0 x50 e Vc = 21 addr :0 x510 Vf = 00 addr :0 x512 Skips the next instruction if Vb equals Vcaddr :0 x514 Vf = 01 addr :0 x516 Vb = Vfaddr :0 x518 Skips the next instruction if Vb not equals 00 addr :0 x51 a jmp 52 eaddr :0 x51 c clear screenaddr :0 x51 e Vb = Vfaddr :0 x520 set I=Veaddr :0 x522 store V0 -Ve to addr start at Iaddr :0 x524 Vf = 03 addr :0 x526 Ve += Vf set VF=1 if VX>=255 addr :0 x528 call 202
202函数为输出dead函数,需要跳过,传入27a中寄存器Vd的值表示多项式前该项的系数,三个三个一组可以列出10个方程,写脚本z3求解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 from z3 import *def RecurOr (flags, models, pos=0 ): if pos <= len (flags) - 1 : return Or(models[flags[pos]] != flags[pos], RecurOr(flags, models, pos + 1 )) else : return Or(models[flags[pos]] != flags[pos]) f = [Int('v%d' % i) for i in range (9 )] flag = [] solver = Solver() for c in f: solver.add(c >= 0x0 ) solver.add(c <= 0xff ) solver.add(f[0 ] + 2 * f[1 ] + f[2 ] == 0x21 ) solver.add(2 * f[0 ] + f[1 ] + f[2 ] == 0x2a ) solver.add(f[0 ] + 2 * f[1 ] + 2 * f[2 ] == 0x30 ) solver.add(f[3 ] + 2 * f[4 ] + f[5 ] == 0x37 ) solver.add(2 * f[3 ] + f[4 ] + f[5 ] == 0x37 ) solver.add(f[3 ] + 2 * f[4 ] + 2 * f[5 ] == 0x3b ) solver.add(f[6 ] + 2 * f[7 ] + f[8 ] == 0x1f ) solver.add(2 * f[6 ] + f[7 ] + f[8 ] == 0x16 ) solver.add(f[6 ] + 2 * f[7 ] + 2 * f[8 ] == 0x20 ) while solver.check() == sat: model = solver.model() ff = [model[f[0 ]].as_long() - 2 , model[f[1 ]].as_long() - 1 , (model[f[2 ]].as_long() ^ 1 ) - 1 , model[f[3 ]].as_long() - 3 , model[f[4 ]].as_long() - 2 , (model[f[5 ]].as_long() - 1 ) ^ 2 , model[f[6 ]].as_long() // 2 , model[f[7 ]].as_long() - 1 , (model[f[8 ]].as_long() - 1 ) ^ 1 , 5 - 2 ] print (ff) solver.add(RecurOr(f, model))
两部分都得到,拼起来提交正确
1 flag {6 c8 f1 d78770 fe672122478 c6 f9 a150 e8 a2 def12 c13 }
Comments