【wp】2021绿城杯

终于良心发现回来水wp的博客了= =

做完RE以后跑去做Misc结果到比赛结束都没做出来,早知道就提早下班了(bushi,有LSB隐写的wp请速dd我T.T

Reverse

easy_re

一个魔改RC4的签到题。

image-20211007144710345

显然有花指令,xor eax, eax以后zf标志位为1,所以jz相当于直接jmp,可以将之间的指令都patch成nop

image-20211007145732920

就是这些垃圾指令,直接nop掉就好(

然后能看到逻辑,就是一个简单的RC4,但是有一点点魔改。

RC4 init(多了一个xor 0x37):

image-20211007150423433

RC4加密过程:

image-20211007150521829

密钥是tallmewhy

image-20211007150857191

最后的密文存在v19开头这里:

image-20211007150933826

动态调一下就能直接拿到密文。

最后exp(拿自己之前写的RC4实现改的):

// By c10udlnk(https://github.com/c10udlnk) // Enjoy it! #include <cstdio> unsigned char S_Box[256]={0}; // RC4 initial 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; } // RC4 Encryption and Decryption (The same) 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]; } } // Hex to Char 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(){ // 所有字符串均为经hex编码后的形式,且为小写字母 // 搭配Python3的binascii.hexlify()使用最佳 // RC4的加密与解密算法相同 // 记得更改对应的dataLen和keyLen 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]); // printf("\n%s",data); return 0; }

666c61677b63356530663566362d663739652d356239622d393838662d3238663034363131373830327dunhex一下有:

flag{c5e0f5f6-f79e-5b9b-988f-28f046117802}

抛石机

没有花指令,逻辑很清晰。

这里是将输入丢进循环中,如果v15[i] = 'x',那么只要sub_1155(v4)>=0就能过check,并将对应字符存入数组v16中。

image-20211007153017036

后面就是把之前存的v16两个一组丢进sub_1198中,并把结果保存进对应的新的数组里。

(有一点乱序存储的感觉,内存里依次是byte_4048byte_4050byte_4058byte_4060

image-20211007153422079

调的时候会发现保存在高四字节中,低四字节默认是零:

Untitled

sub_1155明显是一个单个字母的十六进制转换,而sub_1198就是一个将类似1f转成0x1f的unhex操作。

image-20211007152719087

image-20211007152934792

最终check就是这个浮点数的check,解一个一元二次方程得到两个解,相对大小确定,需要控制一下精度就行:

image-20211007155237141

用sage解一下

image-20210929194539160

然后用这四个浮点数输出几个uint64,然后在十六进制数的基础上调一下精度。

exp:

#include <stdio.h> int main(){ // double b1 = 1.9776226868128955561048266968; // double b2 = 4.3251647224828624129341225296; // double b3 = 1.0806323789664129493847180501; // double b4 = -0.48267319186340060660987720185; // printf("%lx %lx %lx %lx\n", *(unsigned long*)&b1, *(unsigned long*)&b2, *(unsigned long*)&b3, *(unsigned long*)&b4); 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里按顺序组装回去:

l = "3fffa45800000000 40114cf800000000 3ff14a4500000000 bfdee41e00000000".split(' ') l = [x[:8] for x in l] # print(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不会,瞎逆。

后来听出题人说调起来就行了(逃

去掉花指令,可以看到关键加密代码

image-20211007204443723

image-20210929200428012

上面是已知数组,下面可能进行了什么操作,但主操作是xor 0x22和+3,并且循环次数是这个已知数组的长度。

写exp有:

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}


__EOF__

本文作者c10udlnk
本文链接https://www.cnblogs.com/c10udlnk/p/15846183.html
关于博主:欢迎关注我的个人博客-> https://c10udlnk.top/
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   c10udlnk  阅读(315)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示