2021绿城杯 RE WP
Posted 努力学习的大康
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021绿城杯 RE WP相关的知识,希望对你有一定的参考价值。
逆向(100分题)
变异RC4,关键点是密钥盒S的生成过程被魔改了。RC4原理参考之前的博客
基本流程
1.初始循环填充key,key=“tallmewhy”
2.计算密钥盒S,但是不是标准的RC4算法。可以通过dump的方法将密钥和提取
3.ebp+ecx+var_534中是密文
由于不想看魔改的S盒生成算法,所以在S盒生成完成的地方下断点,dump S盒填充就可以了。
exp
#include<stdio.h>
#include<string.h>
struct rc4_state
{
int x, y, m[256];
}rc4_state;
void rc4_setup( struct rc4_state *s, unsigned char *key, int length );
void rc4_crypt( struct rc4_state *s, unsigned char *data, int length );
void rc4_setup( struct rc4_state *s, unsigned char *key, int length )
{
int i, j, k, *m, a;
s->x = 0;
s->y = 0;
m = s->m;
for( i = 0; i < 256; i++ )
{
m[i] = i;
}
j = k = 0;
for( i = 0; i < 256; i++ )
{
a = m[i];
j = (unsigned char) ( j + a + key[k] );
m[i] = m[j]; m[j] = a;
if( ++k >= length ) k = 0;
}
}
void rc4_crypt( struct rc4_state *s, unsigned char *data, int length )
{
int i, x, y, *m, a, b;
x = s->x;
y = s->y;
m = s->m;
for( i = 0; i < length; i++ )
{
x = (unsigned char) ( x + 1 );
a = m[x];
y = (unsigned char) ( y + a );
m[x] = b = m[y];
m[y] = a;
data[i] ^= m[(unsigned char) ( a + b )];
}
s->x = x;
s->y = y;
}
int main()
{
struct rc4_state rc4_ctx;
char* key = "tallmewhy";
unsigned char content[256] = "aaaabbbbccccdddd";
unsigned char encrpyt[256] = {
0xF5,0x8C,0x8D,0xE4,0x9F,0xA5,0x28,0x65,0x30,0xF4,0xEB,0xD3,0x24,0xA9,0x91,0x1A,
0x6F,0xD4,0x6A,0xD7,0x0B,0x8D,0xE8,0xB8,0x83,0x4A,0x5A,0x6E,0xBE,0xCB,0xF4,0x4B,
0x99,0xD6,0xE6,0x54,0x7A,0x4F,0x50,0x14,0xE5,0xEC,0x76,0x00,0x20,0xC9,0xD1,0x00
};
unsigned char mtrix[256] = {
0x74,0x1B,0xD8,0xAC,0x9E,0xB5,0x0B,0x7A,0xFB,0x10,0x8A,0xAB,0x3A,0x72,0x15,0x19
,0x5B,0x18,0x00,0x67,0xE7,0xAA,0x75,0x24,0xB1,0xF4,0xE3,0x89,0x49,0x9F,0x84,0xB5
,0x10,0xD2,0x5C,0x67,0x2A,0x6D,0xCA,0x4A,0x52,0x89,0x4A,0x6A,0x46,0xC5,0x76,0x6D
,0x8A,0xCE,0xE2,0x8C,0x60,0x36,0x06,0xF6,0x0B,0x61,0x39,0xCF,0x62,0xDD,0x7A,0x47
,0xA8,0x95,0x43,0x12,0x41,0xF3,0xFE,0x7F,0x56,0x20,0x0E,0xD3,0x04,0x94,0xB3,0xBA
,0xA0,0xA1,0x3F,0xFA,0x30,0xBC,0xF7,0x53,0xF1,0xC5,0x42,0xF5,0x62,0xA1,0x2F,0x64
,0x91,0xAF,0x44,0x92,0xD8,0x03,0xFA,0x1E,0xA0,0xC7,0xC0,0x71,0x85,0xD0,0xAA,0x6F
,0x05,0x02,0x17,0x47,0xF3,0x30,0x32,0x6B,0xB8,0x04,0x5E,0x83,0xA7,0xA6,0xEB,0x0F
,0xF0,0x2B,0x8E,0xC8,0x08,0x06,0x8B,0xB1,0xF5,0xEA,0xB6,0x2C,0x16,0x38,0x8F,0x99
,0x95,0x4B,0xF4,0x25,0x94,0x68,0x5B,0x35,0xB4,0x58,0xF9,0x79,0x59,0xCB,0x00,0x0A
,0x7E,0x87,0xDF,0xEE,0x93,0xAB,0xC8,0xD4,0xA4,0x24,0xBA,0x98,0x44,0x2E,0x69,0x03
,0x5D,0x77,0xFE,0xD1,0xD7,0xCA,0xEC,0x3E,0xF6,0xAD,0xDB,0x0C,0xD9,0x2D,0x36,0x45
,0xE0,0x23,0xC6,0x77,0x92,0x29,0xE2,0x26,0x09,0x9B,0xED,0x63,0x57,0x78,0xFC,0x79
,0x54,0x3B,0x1A,0x7B,0x2B,0x22,0x80,0x3A,0xE4,0xCC,0x7B,0xBF,0xDE,0x7F,0x68,0x51
,0xAD,0x3D,0x65,0xDA,0x6E,0x1D,0xBF,0xD6,0xF8,0xDE,0x99,0xDC,0xB0,0x78,0xB9,0x85
,0x26,0x1F,0x23,0xE8,0x16,0x28,0xA7,0x66,0xBB,0x4B,0xE1,0xB6,0xE5,0xB7,0xA9,0xD1
};
memset(&rc4_ctx,0,sizeof(rc4_state));
rc4_setup(&rc4_ctx,key,strlen(key));
for(int i=0;i<256;i++)//用dump的密钥盒S修复
{
rc4_ctx.m[i]=mtrix[i];
}
rc4_crypt(&rc4_ctx,encrpyt,strlen(encrpyt));
printf("%s\\n");
printf("\\n");
}
得到最后的flag:flag{c5e0f5f6-f79e-5b9b-988f-28f046117802}
投石机
思路是通过爆破得到4个int32的值。一开始一直不对的原因是大端小端填充的问题。
基本流程
flag的格式为flag{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
之后将char2hex进行转换
给了几个double的限制条件,爆破一下就好了
exp
#include <stdio.h>
int main()
{
for(unsigned long long int i=0;i<0xffffffff;i++)
{
unsigned long long int tmp = i<<32;
double tmp2 = *(double*)(&tmp);
double v4 = 149.2 * tmp2 + tmp2 * (-27.6) * tmp2 - 129.0;
double v2 = tmp2 * (-39.6) * tmp2 + (59.2) * tmp2 + (37.8);
double v1 = tmp2 * (-39.6) * tmp2 + (59.2) * tmp2 + (37.8);
if( v4>-0.00003 && v4<0.00003)
{
printf("v4:%p\\n",i);
}
if(v2>-0.00002 && v2<0.00002)
{
printf("v2:%p\\n",i);
}
if(v1>-0.00003 && v1<0.00003)
{
printf("v1:%p\\n",i);
}
}
return 0;
}
output
v4:0x3ff14a45
v1:0x3fffa458
v4:0x40114cf8
v1:0xbfdee41d
v2:0xbfdee41e
v1:0xbfdee41e
v1:0xbfdee41f
遍历一下或者根据前面的限制条件得到最后的flag
flag{454af13f-f84c-1140-1ee4-debf58a4ff3f}
Vxworks
没做出来,球球师傅教教我
以上是关于2021绿城杯 RE WP的主要内容,如果未能解决你的问题,请参考以下文章