终于良心发现回来水wp的博客了= =
做完RE以后跑去做Misc结果到比赛结束都没做出来,早知道就提早下班了(bushi,有LSB隐写的wp请速dd我T.T
Reverse easy_re 一个魔改RC4的签到题。
显然有花指令,xor eax, eax
以后zf标志位为1,所以jz相当于直接jmp,可以将之间的指令都patch成nop
。
就是这些垃圾指令,直接nop掉就好(
然后能看到逻辑,就是一个简单的RC4,但是有一点点魔改。
RC4 init(多了一个xor 0x37):
RC4加密过程:
密钥是tallmewhy
最后的密文存在v19开头这里:
动态调一下就能直接拿到密文。
最后exp(拿自己之前写的RC4实现改的):
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 #include <cstdio> unsigned char S_Box[256 ]={0 };void Init (unsigned char * key,int keyLen) { unsigned char T[256 ]={0 }; for (int i=0 ;i<256 ;i++){ S_Box[i]=i; T[i]=key[i%keyLen]; } int j=0 ; for (int i=0 ;i<256 ;i++){ j=(j+S_Box[i]+T[i])%256 ; unsigned char tmp=S_Box[i]; S_Box[i]=S_Box[j]; S_Box[j]=tmp^0x37 ; } return ; } void RC4 (unsigned char * key,int keyLen,unsigned char * data,int dataLen) { Init(key,keyLen); int i=0 ,j=0 ; for (int k=0 ;k<dataLen;k++){ i=(i+1 )%256 ; j=(j+S_Box[i])%256 ; unsigned char tmp=S_Box[i]; S_Box[i]=S_Box[j]; S_Box[j]=tmp; data[k]^=S_Box[(S_Box[i]+S_Box[j])%256 ]; } } const char HexChar[16 ]={'0' ,'1' ,'2' ,'3' ,'4' ,'5' ,'6' ,'7' ,'8' ,'9' ,'a' ,'b' ,'c' ,'d' ,'e' ,'f' };void hex2char (unsigned char * hex,unsigned char * chr,int hexLen) { int lastIdx=0 ; for (int i=0 ;i<hexLen;i++){ int index=0 ; for (index=0 ;index<16 ;index++){ if (HexChar[index]==hex[i]) break ; } if (index==16 ){ printf ("Please check your hex string at POSITION [%d] again.\n" ,i); return ; } if (i&1 ) chr[i/2 ]=lastIdx*16 +index; else lastIdx=index; } return ; } int main () { unsigned char key_hex[]="74616c6c6d65776879" ; unsigned char data_hex[]="f58c8de49fa5286530f4ebd324a9911a6fd46ad70b8de8b8834a5a6ebecbf44b99d6e6547a4f5014e5ec" ; int keyLen=9 ,dataLen=42 ; unsigned char key[keyLen+1 ]={0 }; unsigned char data[dataLen+1 ]={0 }; hex2char(key_hex,key,keyLen*2 ); hex2char(data_hex,data,dataLen*2 ); RC4(key,keyLen,data,dataLen); printf ("\n[*]RC4 Encrypt/Decrypt result: " ); for (int i=0 ;i<dataLen;i++) printf ("%02x" ,data[i]); return 0 ; }
把666c61677b63356530663566362d663739652d356239622d393838662d3238663034363131373830327d
unhex一下有:
flag{c5e0f5f6-f79e-5b9b-988f-28f046117802}
抛石机 没有花指令,逻辑很清晰。
这里是将输入丢进循环中,如果v15[i] = 'x'
,那么只要sub_1155(v4)>=0
就能过check,并将对应字符存入数组v16
中。
后面就是把之前存的v16
两个一组丢进sub_1198
中,并把结果保存进对应的新的数组里。
(有一点乱序存储的感觉,内存里依次是byte_4048
、byte_4050
、byte_4058
、byte_4060
)
调的时候会发现保存在高四字节中,低四字节默认是零:
sub_1155
明显是一个单个字母的十六进制转换,而sub_1198
就是一个将类似1f
转成0x1f
的unhex操作。
最终check就是这个浮点数的check,解一个一元二次方程得到两个解,相对大小确定,需要控制一下精度就行:
用sage解一下
然后用这四个浮点数输出几个uint64,然后在十六进制数的基础上调一下精度。
exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #include <stdio.h> int main () { unsigned long b1 = 0x3fffa45800000000 ; unsigned long b2 = 0x40114cf800000000 ; unsigned long b3 = 0x3ff14a4500000000 ; unsigned long b4 = 0xbfdee41e00000000 ; double v4 = 149.2 * *(double *)&b3 + *(double *)&b3 * -27.6 * *(double *)&b3 - 129.0 ; double v3 = 149.2 * *(double *)&b2 + *(double *)&b2 * -27.6 * *(double *)&b2 - 129.0 ; double v2 = *(double *)&b4 * -39.6 * *(double *)&b4 + 59.2 * *(double *)&b4 + 37.8 ; double v1 = *(double *)&b1 * -39.6 * *(double *)&b1 + 59.2 * *(double *)&b1 + 37.8 ; printf ("%lf %lf %lf %lf\n" , v1, v2, v3, v4); printf ("%lx %lx %lx %lx\n" , b1, b2, b3, b4); return 0 ; }
再拿b1~b4的输出丢进python里按顺序组装回去:
1 2 3 4 5 6 7 8 9 10 l = "3fffa45800000000 40114cf800000000 3ff14a4500000000 bfdee41e00000000" .split(' ' ) l = [x[:8 ] for x in l] b = [0 ] for x in l: b.append(bytes .fromhex(x)[::-1 ]) flag = b[3 ] + b[2 ] + b[4 ] + b[1 ] flag = flag.hex () print('flag{' +flag[:8 ]+'-' +flag[8 :12 ]+'-' +flag[12 :16 ]+'-' +flag[16 :20 ]+'-' +flag[20 :]+'}' )
flag{454af13f-f84c-1140-1ee4-debf58a4ff3f}
babyvxworks VxWorks不会,瞎逆。
后来听出题人说调起来就行了(逃
去掉花指令,可以看到关键加密代码
上面是已知数组,下面可能进行了什么操作,但主操作是xor 0x22和+3,并且循环次数是这个已知数组的长度。
写exp有:
1 2 3 4 5 6 7 arr = [188 ,10 ,187 ,193 ,213 ,134 ,127 ,10 ,201 ,185 ,81 ,78 ,136 ,10 ,130 ,185 ,49 ,141 ,10 ,253 ,201 ,199 ,127 ,185 ,17 ,78 ,185 ,232 ,141 ,87 ] flag = [] for x in arr: for _ in range (len (arr)): x = ((x-3 )&0xff ) ^ 0x22 flag.append(x) print('' .join(map (chr , flag)))
flag{helo_w0rld_W3lcome_70_R3}