文章参考:ZJCTF 2021 Triple Language Writeup - 安全客,安全资讯平台
这位师傅太强了。
0x00 日常查壳
0x01 分析主函数
0x02 Check1
input1_part1
k1 = "zjgcjy"
data = [0x2F2E, 0x282A, 0x2C42, 0x2A8A, 0x13E0, 0x36D4]
input1_part1 = ""
for i in range(0, 6):
input1_part1 += chr(data[i] // ord(k1[i]))
print(input1_part1)
input1_part2
from z3 import *
add_data = [0xC2, 0xC3, 0xD7, 0xC4, 0xDA, 0xA5, 0xA0, 0xBE]
sub_data = [0xFC, 0x01, 0xF3, 0xFA, 0x0E, 0xBB, 0x3E, 0x00] #注意小端存储
a = [ BitVec('a%d' % i, 8) for i in range(16) ] #初始化要求的值
input1_part2 = ""
solve = Solver()
for i in range(8):
solve.add(a[i] + a[i + 8] == add_data[i])
solve.add(a[i] - a[i + 8] == sub_data[i])
if sat == solve.check():
ans = solve.model()
for i in range(16):
input1_part2 += chr(ans[a[i]].as_long()) #as_long()转成整数
print(input1_part2)
0x03 Check2
input2_part1
爆破解:
data = [ 0x0, 0x0F26B8303, 0x0E13B70F7, 0x1350F3F4, 0x0C79A971F, 0x35F1141C, 0x26A1E7E8, 0x0D4CA64EB, 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0x0BF284CD3, 0x0AC78BF27, 0x5E133C24, 0x105EC76F, 0x0E235446C, 0x0F165B798, 0x30E349B, 0x0D7C45070, 0x25AFD373, 0x36FF2087, 0x0C494A384, 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0x0AF768BBC, 0x0BC267848, 0x4E4DFB4B, 0x20BD8EDE, 0x0D2D60D, 0x0C186FE29, 0x33ED7D2A, 0x0E72719C1, 0x154C9AC2, 0x61C6936, 0x0F477EA35, 0x0AA64D611, 0x580F5512, 0x4B5FA6E6, 0x0B93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, 0x30E349B1, 0x0C288CAB2, 0x0D1D83946, 0x23B3BA45, 0x0F779DEAE, 0x5125DAD, 0x1642AE59, 0x0E4292D5A, 0x0BA3A117E, 0x4851927D, 0x5B016189, 0x0A96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, 0x417B1DBC, 0x0B3109EBF, 0x0A0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, 0x0CBA24573, 0x39C9C670, 0x2A993584, 0x0D8F2B687, 0x0C38D26C, 0x0FE53516F, 0x0ED03A29B, 0x1F682198, 0x5125DAD3, 0x0A34E59D0, 0x0B01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 0x0DBFC821C, 0x2997011F, 0x3AC7F2EB, 0x0C8AC71E8, 0x1C661503, 0x0EE0D9600, 0x0FD5D65F4, 0x0F36E6F7, 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0x0A65C047D, 0x5437877E, 0x4767748A, 0x0B50CF789, 0x0EB1FCBAD, 0x197448AE, 0x0A24BB5A, 0x0F84F3859, 0x2C855CB2, 0x0DEEEDFB1, 0x0CDBE2C45, 0x3FD5AF46, 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0x0B602C312, 0x44694011, 0x5739B3E5, 0x0A55230E6, 0x0FB410CC2, 0x92A8FC1, 0x1A7A7C35, 0x0E811FF36, 0x3CDB9B, 0x0CEB018DE, 0x0E0EB2A, 0x2F8B6829, 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0x0B7072F64, 0x0A457DC90, 0x563C5F93, 0x82F63B7, 0x0FA44E0B4, 0x0E9141340, 0x1B7F9043, 0x0CFB5F4A8, 0x3E77AB, 0x2E8E845F, 0x0DCE5075C, 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0x0A759E80B, 0x0B4091BFF, 0x466298FC, 0x1871A4D8, 0x0EA1A27DB, 0x0F94AD42F, 0x0B21572C, 0x0DFEB33C7, 0x2D80B0C4, 0x3ED04330, 0x0CCBBC033, 0x0A24BB5A6, 0x502036A5, 0x4370C551, 0x0B11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, 0x2892ED69, 0x0DAF96E6A, 0x0C9A99D9E, 0x3BC21E9D, 0x0EF087A76, 0x1D63F975, 0x0E330A81, 0x0FC588982, 0x0B21572C9, 0x407EF1CA, 0x532E023E, 0x0A145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 0x38CC2A06, 0x0CAA7A905, 0x0D9F75AF1, 0x2B9CD9F2, 0x0FF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0x0EC064EED, 0x0C38D26C4, 0x31E6A5C7, 0x22B65633, 0x0D0D530, 0x417B1DB, 0x0F67C32D8, 0x0E52CC12C, 0x1747422F, 0x49547E0B, 0x0BB3FFD08, 0x0A86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, 0x0D3D3E1AB, 0x21B862A8, 0x32E8915C, 0x0C083125F, 0x144976B4, 0x0E622F5B7, 0x0F5720643, 0x7198540, 0x590AB964, 0x0AB613A67, 0x0B831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC08F, 0x0E330A81A, 0x115B2B19, 0x20BD8ED, 0x0F0605BEE, 0x24AA3F05, 0x0D6C1BC06, 0x0C5914FF2, 0x37FACCF1, 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0x0AE7367CA, 0x5C18E4C9, 0x4F48173D, 0x0BD23943E, 0x0F36E6F75, 0x105EC76, 0x12551F82, 0x0E03E9C81, 0x34F4F86A, 0x0C69F7B69, 0x0D5CF889D, 0x27A40B9E, 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0x0BE2DA0A5, 0x4C4623A6, 0x5F16D052, 0x0AD7D5351, 0x0D76AA478]
#allow = "0123456789abcdefABCDEF" #这种方式不行
allow = string.digits + string.ascii_letters
for i in allow:
for j in allow:
for x in allow:
for y in allow:
tmp = i + j + x + y #构造输入
v1 = 0xFFFFFFFF #初始化数
for z in range(4): #这下面要转成字符码再限制在256以内 原题也是加了个强制转换 unsigned __int8
v1 = ((v1 >> 8) ^ data[ (ord(tmp[z]) ^ v1) & 0xFF ]) & 0xFFFFFFFF #因为python的数是无线大的所以要限制在这个范围
v1 = ~v1 & 0xFFFFFFFF #同理限制在这个范围
if v1 == 0xCAFABCBC:
print(tmp)
exit(0)
Z3解:
from z3 import *
data = [ 0x0, 0x0F26B8303, 0x0E13B70F7, 0x1350F3F4, 0x0C79A971F, 0x35F1141C, 0x26A1E7E8, 0x0D4CA64EB, 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0x0BF284CD3, 0x0AC78BF27, 0x5E133C24, 0x105EC76F, 0x0E235446C, 0x0F165B798, 0x30E349B, 0x0D7C45070, 0x25AFD373, 0x36FF2087, 0x0C494A384, 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0x0AF768BBC, 0x0BC267848, 0x4E4DFB4B, 0x20BD8EDE, 0x0D2D60D, 0x0C186FE29, 0x33ED7D2A, 0x0E72719C1, 0x154C9AC2, 0x61C6936, 0x0F477EA35, 0x0AA64D611, 0x580F5512, 0x4B5FA6E6, 0x0B93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, 0x30E349B1, 0x0C288CAB2, 0x0D1D83946, 0x23B3BA45, 0x0F779DEAE, 0x5125DAD, 0x1642AE59, 0x0E4292D5A, 0x0BA3A117E, 0x4851927D, 0x5B016189, 0x0A96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, 0x417B1DBC, 0x0B3109EBF, 0x0A0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, 0x0CBA24573, 0x39C9C670, 0x2A993584, 0x0D8F2B687, 0x0C38D26C, 0x0FE53516F, 0x0ED03A29B, 0x1F682198, 0x5125DAD3, 0x0A34E59D0, 0x0B01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 0x0DBFC821C, 0x2997011F, 0x3AC7F2EB, 0x0C8AC71E8, 0x1C661503, 0x0EE0D9600, 0x0FD5D65F4, 0x0F36E6F7, 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0x0A65C047D, 0x5437877E, 0x4767748A, 0x0B50CF789, 0x0EB1FCBAD, 0x197448AE, 0x0A24BB5A, 0x0F84F3859, 0x2C855CB2, 0x0DEEEDFB1, 0x0CDBE2C45, 0x3FD5AF46, 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0x0B602C312, 0x44694011, 0x5739B3E5, 0x0A55230E6, 0x0FB410CC2, 0x92A8FC1, 0x1A7A7C35, 0x0E811FF36, 0x3CDB9B, 0x0CEB018DE, 0x0E0EB2A, 0x2F8B6829, 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0x0B7072F64, 0x0A457DC90, 0x563C5F93, 0x82F63B7, 0x0FA44E0B4, 0x0E9141340, 0x1B7F9043, 0x0CFB5F4A8, 0x3E77AB, 0x2E8E845F, 0x0DCE5075C, 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0x0A759E80B, 0x0B4091BFF, 0x466298FC, 0x1871A4D8, 0x0EA1A27DB, 0x0F94AD42F, 0x0B21572C, 0x0DFEB33C7, 0x2D80B0C4, 0x3ED04330, 0x0CCBBC033, 0x0A24BB5A6, 0x502036A5, 0x4370C551, 0x0B11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, 0x2892ED69, 0x0DAF96E6A, 0x0C9A99D9E, 0x3BC21E9D, 0x0EF087A76, 0x1D63F975, 0x0E330A81, 0x0FC588982, 0x0B21572C9, 0x407EF1CA, 0x532E023E, 0x0A145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 0x38CC2A06, 0x0CAA7A905, 0x0D9F75AF1, 0x2B9CD9F2, 0x0FF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0x0EC064EED, 0x0C38D26C4, 0x31E6A5C7, 0x22B65633, 0x0D0D530, 0x417B1DB, 0x0F67C32D8, 0x0E52CC12C, 0x1747422F, 0x49547E0B, 0x0BB3FFD08, 0x0A86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, 0x0D3D3E1AB, 0x21B862A8, 0x32E8915C, 0x0C083125F, 0x144976B4, 0x0E622F5B7, 0x0F5720643, 0x7198540, 0x590AB964, 0x0AB613A67, 0x0B831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC08F, 0x0E330A81A, 0x115B2B19, 0x20BD8ED, 0x0F0605BEE, 0x24AA3F05, 0x0D6C1BC06, 0x0C5914FF2, 0x37FACCF1, 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0x0AE7367CA, 0x5C18E4C9, 0x4F48173D, 0x0BD23943E, 0x0F36E6F75, 0x105EC76, 0x12551F82, 0x0E03E9C81, 0x34F4F86A, 0x0C69F7B69, 0x0D5CF889D, 0x27A40B9E, 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0x0BE2DA0A5, 0x4C4623A6, 0x5F16D052, 0x0AD7D5351, 0x0D76AA478]
input2_part1 = ""
solve = Solver()
a = Array('a', BitVecSort(32), BitVecSort(32)) #创建一个每个元素32位的数组
for i in range(256):
solve.add(a[i] == data[i])
input = [BitVec('input%d' % i, 8) for i in range(4)] #初始化要求解的量
t = BitVec('v1', 32)
solve.add(t == 0xFFFFFFFF)
for i in range(4):
idx = (ZeroExt(24, input[i]) ^ t ) & 0xFF #由于t是32位数 所以异或也要32位数 于是我们的输入的高24位补0
t = LShR(t, 8) ^ a[idx] #右移8位
t = ~t
solve.add(t == 0xCAFABCBC)
if solve.check() == sat
ans = solve.model()
for i in range(4):
input2_part1 += chr(ans[input[i]].as_long())
print(input2_part1)
input2_part2
from z3 import *
input = [ BitVec('input[%d]' % i, 8) for i in range(0x1D) ] #初始化变量
data = [0x29 + 15, 0x38 ^ 0x6f, 0x46 - 12, 0x50 ^ 0x12, 0x3E - 5, 0x36 + 33, 0x5E - 12, 0x42 ^ 0xd, 0x3D - 3, 0x47 + 15,
0x36 ^ 0x68, 0x40 ^ 0xA, 0x3E - 5, 0x58 - 33, 0x2A + 48, 0x50 ^ 0x18, 0x3C + 2, 0x47 - 16, 0x3D ^ 0x1B, 0x42 + 6,
0x29 ^ 0x13, 0x31, 0x20, 0x20]
s = Solver()
index = -1 #模仿指针
for i in range(0, 13, 3):
index += 1
s.add( ((input[i] >> 2) + 33) == data[index] ) #这里的一条条语句直接复制 不要手打... 复制肯定不会出错
index += 1
s.add( ( ((16 * input[i]) & 0x30 | (input[i + 1] >> 4)) + 33 ) == data[index])
index += 1
s.add( ( ((4 * input[i + 1]) & 0x3C | (input[i + 2] >> 6)) + 33 ) == data[index])
index += 1
s.add( ( (input[i + 2] & 0x3F) + 33 ) == data[index] )
i = 15
if i <= 15:
index += 1
s.add( ((input[i] >> 2) + 33) == data[index] )
index += 1
if (i == 15):
s.add( (((16 * input[15]) & 0x30) + 33) == data[index] )
index += 1
s.add( 32 == data[index] )
index += 1
s.add( 32 == data[index] )
if sat == s.check():
ans = s.model()
input2_part2 = ""
for i in range(16):
input2_part2 += chr( ans[input[i]].as_long() )
print(input2_part2)
0x04 GetFlag
GetFlag!