查看原文
其他

网刃杯逆向wp

s1lenc3沉默 看雪学苑 2022-07-01


本文为看雪论坛优秀文章
看雪论坛作者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



球分享

球点赞

球在看



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

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存