ZJCTF-Triple Language Write up

本文详细介绍了如何使用Z3进行符号执行来解决CTF比赛中的字符串解密问题。首先通过Python代码演示了两个解密过程,一个是通过循环和异或操作,另一个涉及复杂的位运算和数组索引计算。这些解密挑战涉及了二进制安全、加密算法和编程技巧,展示了在逆向工程和安全分析中的常见技术。
摘要由CSDN通过智能技术生成

 文章参考: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!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值