网刃杯逆向wp

资讯 作者:看雪学院 2021-10-05 23:37:50 阅读:538


本文为看雪论坛优秀文章
看雪论坛作者ID:s1lenc3沉默



re1


根据常数搜索到Sm3,然后爆破就行。
ss = ['6b8575c6092240cde08414dafd535bee', 'f0f659f2951290ad5e076b3fe5e70425', 'c1d6c663570de9fad13ddef955d8a02b', '14c4e442fba6d820ea90ae73ed90ad83', '25d997669868d0cf89782349256efb33', '78b1ea6bb1ac10287864c8f52d2758b6', '67d1259c26765356ddb58c6faf28080c', 'c1e14e0c86f55ba1d74b35b66f96ad36', '3e4f3ee942d1a57182e24df201b7022b', 'c35557f7e5c389061fb2e2ffa1a644ad', '15593844fae18fe1a25f3a9017c73810', 'c6c21ca591a63755fd77bf5c55a0238a', 'f90cb529875e83cc191c0e10ead6f73e', '3ddbe25f9b183c3e2c33c3b1e501fcd8', '30fdf04c347f1d4e335bda670d54eaaf', '33feb100c8c7c3769af6e9d26486c646']m = '77'IV='7380166f4914b2b9172442d7da8a0600a96f30bc163138aae38dee4db0fb0e4e'#填充函数def filling(m):    #消息m是一个16进制字符串    #直接加16进制比较好    #61626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364     #a = int(m,16)    #b = bin(a)[2:]#消息转换为二进制    length_b = len(m)*4#记录消息的长度    #s1='{:04b}'.format(s1)    b = m    b = b + '8'#补 1    c = len(b)%128    c = 112 - c#补 0 的个数    d = '0'*c    b = b + d#补 0    length_m = '{:016x}'.format(length_b)#也是16进制    b = b + length_m#填充完毕    #b = int(b)    #b = hex(b)[2:]    return b #分组函数def fenzu(m):    m = filling(m)    len_m = len(m)/128    m_list = []    for i in range(int(len_m)):        a = m[0+128*i:+128*(i+1)]        m_list.append(a)    return m_list #扩展函数def expand(m,n):#n代表是第几组消息,消息之间没有关系,不用迭代    B = fenzu(m)#列表    W = ['0' for i in range(68)]    W_0 = ['0' for i in range(64)]    for i in range(int(len(B[n])/8)):#128/8=16个字        w = B[n][i*8:(i+1)*8]        W[i] = w    for j in range(16,68):        a = or_16(W[j-16],W[j-9])         W_j_3 = Cyc_shift(W[j-3],15)        #print(W_j_3)        a = or_16(a,W_j_3)         a = Replace_P1(a)        #print(a)        W_j_13=Cyc_shift(W[j-13],7)        a = or_16(a,W_j_13)        a = or_16(a,W[j-6])        W[j]=a    #return W    for j in range(64):        W_0[j]=or_16(W[j],W[j+4])    return W,W_0 #置换函数def Replace_P1(X):    #X为32位字    X_15 = Cyc_shift(X,15)  #循环移位    X_23 = Cyc_shift(X,23)    a = or_16(X,X_15)    a = or_16(a,X_23)    return a #置换函数def Replace_P0(X):    #X为32位字    X_9 = Cyc_shift(X,9)    X_17 = Cyc_shift(X,17)    a = or_16(X,X_9)    a = or_16(a,X_17)    return a #异或函数def or_16(A,B):    A = int(A,16)    B = int(B,16)    C = A ^ B    C = '{:08x}'.format(C)    return C #循环移位函数def Cyc_shift(W,n):    a = int(W,16)    a = '{:032b}'.format(a)    while n>=32:        n=n-32    a = a[n:] + a[:n]    a = int(a,2)    a = '{:08x}'.format(a)    return a #常量Tjdef T_j(j):    if j<=15:        T_j='79cc4519'    else:        T_j='7a879d8a'    return T_j #mod 2^32 算术加运算def add(x,y):    x = int(x,16)    x = '{:032b}'.format(x)    x = list(x)    y = int(y, 16)    y = '{:032b}'.format(y)    y = list(y)    #print(x)    #print(y)    a = [0 for _ in range(32)]    carry = 0    for i in range(32):        m = int(x[31-i])+int(y[31-i])+carry        if m>=2:            d=m-2            a[31-i]=str(d)            carry=1        else:            carry=0            d=m            a[31 - i] = str(d)    #print(a)    b=''.join(a)    b=int(b,2)    b='{:08x}'.format(b)    return b #布尔函数def FF_j(X,Y,Z,j):    if j<=15:        a = or_16(X,Y)        a = or_16(a,Z)    else:        a = and_Cal(X,Y)        b = and_Cal(X,Z)        c = and_Cal(Y,Z)        a = or_Cal(a,b)        a = or_Cal(a,c)    return a #布尔函数def GG_j(X, Y, Z, j):    if j <= 15:        a = or_16(X, Y)        a = or_16(a, Z)    else:        a = and_Cal(X,Y)        b = qufan(X)        b = and_Cal(b,Z)        a = or_Cal(a,b)    return a #与运算函数def and_Cal(a,b):    a = int(a,16)    b = int(b,16)    a_b = a & b    a_b = '{:08x}'.format(a_b)    return a_b #或运算函数def or_Cal(a,b):    a = int(a, 16)    b = int(b, 16)    a_b = a | b    a_b = '{:08x}'.format(a_b)    return a_b #按位取反函数def qufan(A):    A = int(A,16)    A = '{:032b}'.format(A)    A = list(A)    for i in range(32):        if A[i]=='0':            A[i]='1'        else:            A[i]='0'    A = ''.join(A)    A = int(A,2)    A = '{:08x}'.format(A)    return A #压缩函数m_list = fenzu(m)m_len = len(m_list)V = ['0' for i in range(m_len+1)]V[0]=IV #压缩函数def CF(m,n,k):    w = expand(m, n)    W = w[0]    W_0 = w[1]    A=V[k][0:8]    B=V[k][8:16]    C=V[k][16:24]    D=V[k][24:32]    E=V[k][32:40]    F=V[k][40:48]    G=V[k][48:56]    H=V[k][56:64]    #print(W_0)    all=''    for j in range(64):        #print(E)        b= a = Cyc_shift(A,12)        #t = b        T = T_j(j)        #        T = Cyc_shift(T,j)#忘记移位了,移位问题        a = add(a,E)        a = add(a,T)        SS1 = Cyc_shift(a,7)        SS2 = or_16(SS1,b)        b = FF_j(A,B,C,j)        b = add(b,D)        b = add(b,SS2)        TT1 = add(b,W_0[j]) #        b = GG_j(E,F,G,j)        b = add(b, H)        b = add(b, SS1)        TT2 = add(b, W[j]) #        D = C        C = Cyc_shift(B,9)        B = A        A = TT1#        H = G        G = Cyc_shift(F,19)        F = E        E = Replace_P0(TT2) #        all = A+B+C+D+E+F+G+H        #print(all)    #V[k+1]=or_16(all,V[k])    #return V[k+1]    #print(t)    #return all    V[k+1]=or_16(V[k],all) #print(CF(m,0,0))#print(V)def hash(m=m):    for i in range(m_len):        v_n=CF(m,i,i)    #print(V[-1])    return V[-1] #b=''#b=a[0:8]+'\0'+a[8:16]+'\0'+a[16:24]+'\0'+a[24:32]+'\0'+a[32:40]+'\0'+a[40:48]+'\0'+a[48:56]+'\0'+a[56:64]#print(b)flag = ""ttt = ""for j in range(len(ss)):    for i in range(0xff):        arg = ttt + hex(i)[2:].rjust(2,"0")        res = hash(m=arg)[:32]        #print(res, i)        if res == ss[j]:            flag += chr(i)            ttt += hex(i)[2:].rjust(2,"0")            print(flag)            break#print('输入的消息m是:\n',m)#print('消息m的hash值为:\n',b)


re2


本来用unicorn可以秒这道题,但是不知道我多蠢,模拟了一个自己patch过的文件,导致没跑出来,解出这个题之后才发觉,所以写两种方法。
 
两个地方反调试:

 
这里也需要过跳转:
 
 
关键地方就是check分数,得到正确的分数进行简单计算即可:
 

 
要得到score,patch反调试,然后程序内改汇编进行爆破。
 
.text:00992388 90 nop
.text:00992389
.text:00992389 loc_992389: ; CODE XREF: sub_992290+12C↓j
.text:00992389 8B 8D 68 FF FF FF mov ecx, [ebp+var_98]
.text:0099238F 8B 01 mov eax, [ecx+0]
.text:00992391 83 C0 01 add eax, 1
.text:00992394 89 01 mov [ecx], eax
.text:00992396 89 41 4C mov [ecx+4Ch], eax
.text:00992399 90 nop
.text:0099239A 90 nop
.text:0099239B 90 nop
.text:0099239C 90 nop
 
拿到分数。
v12 = 0x2100flag = ""a1 = 0x2100 ^ 0xAC0B while(v12):    v9 = v12 % 8 + 48    flag += chr(v9)    v12 //= 8print("flag{" + "b0d8" + flag + "}")

unicorn模拟程序爆破解法:
from unicorn import *from unicorn.x86_const import *from pwn import * score = 0def read(name):    with open(name,"rb") as fp:        return fp.read()def hook_code(mu, address, size, user_data):    #print('>>> Tracing instruction at 0x%x, instruction size = 0x%x' % (address, size))    #bytes = mu.mem_read(address, 20)    #print('地址:%x, 内容:%s' % (address, binascii.b2a_hex(bytes)))     if address == 0x4017ac:        mu.reg_write(UC_X86_REG_EAX, 0x500000)        mu.reg_write(UC_X86_REG_ECX, 0x500000)        mu.reg_write(UC_X86_REG_EIP, 0x4017b2)    if address == 0x401c2f:        eax = mu.reg_read(UC_X86_REG_EAX)        result = u32(mu.mem_read(BASE+0x10004c,4))        if eax == 0x1a8cd:            print("score: " + hex(result))            global score            score = result            mu.reg_write(UC_X86_REG_EIP, 0x401c31)        else:            mu.mem_write(BASE+0x10004c, p32(result+1))            mu.reg_write(UC_X86_REG_EIP, 0x4017ac) # 模拟器开始的内存地址BASE = 0x400000STACK_ADDR = 0Xf00000#栈大小STACK_SIZE = 1024 * 1024  # 1MB print("Emulate revers2.exe:")try:    #初始化模拟器为x86_32    mu = Uc(UC_ARCH_X86, UC_MODE_32)    #为这个模拟器分配1M内存    mu.mem_map(BASE, 2 * 1024 * 1024, UC_PROT_ALL)    mu.mem_map(STACK_ADDR, STACK_SIZE)    #将程序内容写入内存    mu.mem_write(BASE, read("./revers2.exe"))    mu.mem_write(BASE+0x10004c, b"\x00\x00\x00\x00")    mu.mem_write(0x40733c, b"\x00\x00\x00\x3f\x00\x00\xc0\x3f\x00\x00\xa0\x40\x00\x00\x20\x41\x80\x96\x18\x4b")    mu.reg_write(UC_X86_REG_ESP, STACK_ADDR + STACK_SIZE - 1)    mu.hook_add(UC_HOOK_CODE, hook_code)    mu.emu_start(0x4017ac, 0x401c31) except UcError as e:    print("ERROR: %s" % e) flag = ""a1 = score ^ 0xAC0Bwhile(score):    v9 = score % 8 + 48    flag += chr(v9)    score //= 8print("flag{" + ''.join(reversed(list(hex(a1)[2:]))) + flag + "}")



 


看雪ID:s1lenc3沉默

https://bbs.pediy.com/user-home-906665.htm

*本文由看雪论坛 s1lenc3沉默 原创,转载请注明来自看雪社区



官网:https://www.bagevent.com/event/6334937



# 往期推荐

1.CVE-2012-0003 winmm.dll MIDI文件堆溢出漏洞分析及利用

2.驱动级VT技术EPT实现无痕HOOK保护指定进程----VT EPT原理解析和进阶

3.羊城杯OddCode题解(unicorn模拟调试+求解)

4.从两道0解题看Linux内核堆上msg_msg对象扩展利用

5.新人PWN堆Heap总结off-by-null专场

6. CVE-2012-3569 VMware OVF Tool格式化字符串漏洞分析



公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com



球分享

球点赞

球在看



点击“阅读原文”,了解更多!

在线申请SSL证书行业最低 =>立即申请

[广告]赞助链接:

关注数据与安全,洞悉企业级服务市场:https://www.ijiandao.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

#
公众号 关注KnowSafe微信公众号
随时掌握互联网精彩
赞助链接