羊城杯-RE

login

pyinstaller打包,用工具解一下,得到login.pyc修复一下文件头,反编译解方程组。

from z3  import *
s=Solver()
code=[BitVec(('x%d'%i),32) for i in range(14)]
a1 = code[2]
a2 = code[1]
a3 = code[0]
a4 = code[3]
a5 = code[4]
a6 = code[5]
a7 = code[6]
a8 = code[7]
a9 = code[9]
a10 = code[8]
a11 = code[10]
a12 = code[11]
a13 = code[12]
a14 = code[13]

s.add((((a1 * 88 + a2 * 67 + a3 * 65 - a4 * 5) + a5 * 43 + a6 * 89 + a7 * 25 + a8 * 13 - a9 * 36) + a10 * 15 + a11 * 11 + a12 * 47 - a13 * 60) + a14 * 29 == 22748)
s.add((((a1 * 89 + a2 * 7 + a3 * 12 - a4 * 25) + a5 * 41 + a6 * 23 + a7 * 20 - a8 * 66) + a9 * 31 + a10 * 8 + a11 * 2 - a12 * 41 - a13 * 39) + a14 * 17 == 7258)
s.add((((a1 * 28 + a2 * 35 + a3 * 16 - a4 * 65) + a5 * 53 + a6 * 39 + a7 * 27 + a8 * 15 - a9 * 33) + a10 * 13 + a11 * 101 + a12 * 90 - a13 * 34) + a14 * 23 == 26190)
s.add((((a1 * 23 + a2 * 34 + a3 * 35 - a4 * 59) + a5 * 49 + a6 * 81 + a7 * 25 + (a8 << 7) - a9 * 32) + a10 * 75 + a11 * 81 + a12 * 47 - a13 * 60) + a14 * 29 == 37136)
s.add(((a1 * 38 + a2 * 97 + a3 * 35 - a4 * 52) + a5 * 42 + a6 * 79 + a7 * 90 + a8 * 23 - a9 * 36) + a10 * 57 + a11 * 81 + a12 * 42 - a13 * 62 - a14 * 11 == 27915)
s.add((((a1 * 22 + a2 * 27 + a3 * 35 - a4 * 45) + a5 * 47 + a6 * 49 + a7 * 29 + a8 * 18 - a9 * 26) + a10 * 35 + a11 * 41 + a12 * 40 - a13 * 61) + a14 * 28 == 17298)
s.add((((a1 * 12 + a2 * 45 + a3 * 35 - a4 * 9 - a5 * 42) + a6 * 86 + a7 * 23 + a8 * 85 - a9 * 47) + a10 * 34 + a11 * 76 + a12 * 43 - a13 * 44) + a14 * 65 == 19875)
s.add(((a1 * 79 + a2 * 62 + a3 * 35 - a4 * 85) + a5 * 33 + a6 * 79 + a7 * 86 + a8 * 14 - a9 * 30) + a10 * 25 + a11 * 11 + a12 * 57 - a13 * 50 - a14 * 9 == 22784)
s.add((((a1 * 8 + a2 * 6 + a3 * 64 - a4 * 85) + a5 * 73 + a6 * 29 + a7 * 2 + a8 * 23 - a9 * 36) + a10 * 5 + a11 * 2 + a12 * 47 - a13 * 64) + a14 * 27 == 9710)
s.add(((((a1 * 67 - a2 * 68) + a3 * 68 - a4 * 51 - a5 * 43) + a6 * 81 + a7 * 22 - a8 * 12 - a9 * 38) + a10 * 75 + a11 * 41 + a12 * 27 - a13 * 52) + a14 * 31 == 13376)
s.add((((a1 * 85 + a2 * 63 + a3 * 5 - a4 * 51) + a5 * 44 + a6 * 36 + a7 * 28 + a8 * 15 - a9 * 6) + a10 * 45 + a11 * 31 + a12 * 7 - a13 * 67) + a14 * 78 == 24065)
s.add((((a1 * 47 + a2 * 64 + a3 * 66 - a4 * 5) + a5 * 43 + a6 * 112 + a7 * 25 + a8 * 13 - a9 * 35) + a10 * 95 + a11 * 21 + a12 * 43 - a13 * 61) + a14 * 20 == 27687)
s.add(((a1 * 89 + a2 * 67 + a3 * 85 - a4 * 25) + a5 * 49 + a6 * 89 + a7 * 23 + a8 * 56 - a9 * 92) + a10 * 14 + a11 * 89 + a12 * 47 - a13 * 61 - a14 * 29 == 29250)
s.add(((a1 * 95 + a2 * 34 + a3 * 62 - a4 * 9 - a5 * 43) + a6 * 83 + a7 * 25 + a8 * 12 - a9 * 36) + a10 * 16 + a11 * 51 + a12 * 47 - a13 * 60 - a14 * 24 == 15317)
if s.check()==sat:
    print "sat"
    print s.model()
else:
    print "un"

方程组解完再异或运算一下

#include
#include 

int main()
{
     
	char szpassword[14] = {
     10,0x18,0x77,7,104,43,28,91,108,0x34,0x58,0x4a,0x58,33 };
	//char szpassword[14] = {10,24,119,7,104,43,28,91,52,108,88,74,88,33 };
	char a[16] ;
	for (int i = 13; i >=0; i--)
	{
     
		szpassword[i - 1] ^= szpassword[i];
		
	}
	for (int i = 0; i < 14; i++)
	{
     
		printf("%c", szpassword[i]);
	}
	printf("\n");
	
	getchar();
}

得到flag,再md5加密一下提交

Bytecode

手撕py机器码,得到正向算法类似如下

mport dis 
def hello():
    x=[]
    en=[3,37,72,9,6,132]
    flag="1234567890123456"
    a=ord(flag[0])*2020+ord(flag[1])*2020
    k=5
    for i in range(13):
        b= ord(flag[k])
        c=ord(flag[k+1])
        a11=en[i%6]^c
        a22=en[i%6]^b
        x.append(a22)
        x.append(a11)
        k=k+2
    l=len(flag)
    a1=ord(flag[l-7])
    a2=ord(flag[l-6])
    a3=ord(flag[l-5])
    a4=ord(flag[l-4])
    a5=ord(flag[l-3])
    a6=ord(flag[l-2])
    if a1*3+a2*2+a3*5==1003:
        print 1
    if a1*4+a2*7+a3*9==2013:
        print 1
    if a2*8+a1+2*a3==1109:
        print 1
    if a4*3+a5*2+a6*5==671:
        print 1
    if a4*4+a5*7+a6*9==1252:
        print 1
    if a5*8+a4+a6*2==644:
        print 1
dis.dis(hello)

其中前5位不是很好算不过可以猜到是GWHT{

后面是一段异或解密如下

int main()
{
     
	int en[6] = {
     3, 37, 72, 9, 6, 132};
	int output[26] = {
      101, 96, 23, 68, 112, 42, 107, 62, 96, 53, 176, 179, 98, 53, 67, 29, 41, 120, 60, 106, 51, 101, 178, 189, 101, 48 };
	int k = 0;
	for (int i = 0; i < 13; i++)
	{
     
		printf("%c", output[k+1] ^ en[i % 6]);
		printf("%c", output[k] ^ en[i % 6]);
		k = k + 2;
	}
	getchar();
}

最后6位解方程组

from z3 import *
s=Solver()
a1=Int('a1')
a2=Int('a2')
a3=Int('a3')
a4=Int('a4')
a5=Int('a5')
a6=Int('a6')
s.add(a1*3+a2*2+a3*5==1003)
s.add(a1*4+a2*7+a3*9==2013)
s.add(a2*8+a1+2*a3==1109)
s.add(a4*3+a5*2+a6*5==671)
s.add(a4*4+a5*7+a6*9==1252)
s.add(a5*8+a4+a6*2==644)
if s.check()==sat:
    print "sat"
    print s.model()
else:
    print "un"

babyre

首先是一个Des解密,这里用gdb调试将解密数据作为输入数据,DES_ncbc_encryp最后一个参数改为0,即可得到key:th1s1sth3n1c3k3y

之后将内存dUmp下来再修复一下自解码

a=[0x55, 0x48, 0x89, 0xE5, 0x48, 0x81, 0xEC, 0x40, 0x01, 0x00, 0x00, 0x48, 0x89, 0xBD, 0xC8, 0xFE, 0xFF, 0xFF, 0x64, 0x48, 0x8B, 0x04, 0x25, 0x28, 0x00, 0x00, 0x00, 0x48, 0x89, 0x45, 0xF8, 0x31, 0xC0, 0x48, 0x8D, 0x45, 0xB0, 0x48, 0x89, 0xC6, 0xBF, 0xE0, 0x2F, 0x40, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x2C, 0xE1, 0xFF, 0xFF, 0x48, 0x8D, 0x45, 0xB0, 0x48, 0x89, 0xC7, 0xE8, 0x00, 0xE1, 0xFF, 0xFF, 0x89, 0x85, 0xEC, 0xFE, 0xFF, 0xFF, 0x83, 0xBD, 0xEC, 0xFE, 0xFF, 0xFF, 0x20, 0x74, 0x14, 0xBF, 0xE5, 0x2F, 0x40, 0x00, 0xE8, 0x97, 0xE0, 0xFF, 0xFF, 0xBF, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x9D, 0xE0, 0xFF, 0xFF, 0x48, 0x8B, 0x95, 0xC8, 0xFE, 0xFF, 0xFF, 0x48, 0x8D, 0x85, 0xF0, 0xFE, 0xFF, 0xFF, 0x48, 0x89, 0xD6, 0x48, 0x89, 0xC7, 0xE8, 0xE5, 0xE4, 0xFF, 0xFF, 0x48, 0x8D, 0x55, 0xB0, 0x48, 0x8D, 0x85, 0xF0, 0xFE, 0xFF, 0xFF, 0x48, 0x89, 0xD6, 0x48, 0x89, 0xC7, 0xE8, 0xCC, 0xF3, 0xFF, 0xFF, 0x48, 0x8D, 0x45, 0xB0, 0x48, 0x83, 0xC0, 0x10, 0x48, 0x8D, 0x95, 0xF0, 0xFE, 0xFF, 0xFF, 0x48, 0x89, 0xC6, 0x48, 0x89, 0xD7, 0xE8, 0xB2, 0xF3, 0xFF, 0xFF, 0xC7, 0x85, 0xD8, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xEB, 0x5B, 0xC7, 0x85, 0xDC, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xEB, 0x2F, 0x8B, 0x85, 0xD8, 0xFE, 0xFF, 0xFF, 0x48, 0x98, 0x0F, 0xB6, 0x54, 0x05, 0xB0, 0x8B, 0x85, 0xDC, 0xFE, 0xFF, 0xFF, 0x48, 0x98, 0x0F, 0xB6, 0x44, 0x05, 0xB0, 0x31, 0xC2, 0x8B, 0x85, 0xD8, 0xFE, 0xFF, 0xFF, 0x48, 0x98, 0x88, 0x54, 0x05, 0xB0, 0x83, 0x85, 0xDC, 0xFE, 0xFF, 0xFF, 0x01, 0x8B, 0x85, 0xD8, 0xFE, 0xFF, 0xFF, 0x8D, 0x50, 0x03, 0x85, 0xC0, 0x0F, 0x48, 0xC2, 0xC1, 0xF8, 0x02, 0x3B, 0x85, 0xDC, 0xFE, 0xFF, 0xFF, 0x7F, 0xB8, 0x83, 0x85, 0xD8, 0xFE, 0xFF, 0xFF, 0x01, 0x83, 0xBD, 0xD8, 0xFE, 0xFF, 0xFF, 0x1F, 0x7E, 0x9C, 0xC7, 0x85, 0xE0, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0xC7, 0x85, 0xE4, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0xE9, 0x8C, 0x00, 0x00, 0x00, 0xC6, 0x85, 0xD7, 0xFE, 0xFF, 0xFF, 0x00, 0x8B, 0x85, 0xE4, 0xFE, 0xFF, 0xFF, 0x83, 0xE8, 0x01, 0x48, 0x98, 0x0F, 0xB6, 0x44, 0x05, 0xB0, 0x83, 0xF0, 0x13, 0x01, 0xC0, 0x83, 0xC0, 0x07, 0x89, 0xC6, 0x8B, 0x85, 0xE4, 0xFE, 0xFF, 0xFF, 0x83, 0xE8, 0x01, 0x48, 0x98, 0x0F, 0xB6, 0x4C, 0x05, 0xB0, 0x0F, 0xB6, 0xD1, 0x89, 0xD0, 0xC1, 0xE0, 0x03, 0x29, 0xD0, 0xC1, 0xE0, 0x03, 0x01, 0xD0, 0x66, 0xC1, 0xE8, 0x08, 0x89, 0xC2, 0xD0, 0xEA, 0x89, 0xD0, 0xC1, 0xE0, 0x03, 0x01, 0xD0, 0x29, 0xC1, 0x89, 0xCA, 0x8B, 0x85, 0xE4, 0xFE, 0xFF, 0xFF, 0x48, 0x98, 0x0F, 0xB6, 0x44, 0x05, 0xB0, 0x01, 0xD0, 0x83, 0xC0, 0x02, 0x31, 0xF0, 0x88, 0x85, 0xD7, 0xFE, 0xFF, 0xFF, 0x8B, 0x85, 0xE4, 0xFE, 0xFF, 0xFF, 0x83, 0xE8, 0x01, 0x48, 0x98, 0x0F, 0xB6, 0x95, 0xD7, 0xFE, 0xFF, 0xFF, 0x88, 0x90, 0xD0, 0x40, 0x60, 0x00, 0x83, 0x85, 0xE4, 0xFE, 0xFF, 0xFF, 0x01, 0x83, 0xBD, 0xE4, 0xFE, 0xFF, 0xFF, 0x1F, 0x0F, 0x8E, 0x67, 0xFF, 0xFF, 0xFF, 0x0F, 0xB6, 0x45, 0xCF, 0x3C, 0xC4, 0x75, 0x48, 0xC7, 0x85, 0xE8, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xEB, 0x33, 0x8B, 0x85, 0xE8, 0xFE, 0xFF, 0xFF, 0x48, 0x98, 0x0F, 0xB6, 0x90, 0xD0, 0x40, 0x60, 0x00, 0x8B, 0x85, 0xE8, 0xFE, 0xFF, 0xFF, 0x48, 0x98, 0x0F, 0xB6, 0x80, 0x00, 0x41, 0x60, 0x00, 0x38, 0xC2, 0x74, 0x0A, 0xC7, 0x85, 0xE0, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x83, 0x85, 0xE8, 0xFE, 0xFF, 0xFF, 0x01, 0x83, 0xBD, 0xE8, 0xFE, 0xFF, 0xFF, 0x1E, 0x7E, 0xC4, 0x8B, 0x85, 0xE0, 0xFE, 0xFF, 0xFF, 0x48, 0x8B, 0x4D, 0xF8, 0x64, 0x48, 0x33, 0x0C, 0x25, 0x28, 0x00, 0x00, 0x00, 0x74, 0x05, 0xE8, 0x18, 0xDF, 0xFF, 0xFF, 0xC9, 0xC3, 0x55, 0x48, 0x89, 0xE5, 0x48, 0x81, 0xEC, 0x40, 0x01, 0x00, 0x00, 0x64, 0x48, 0x8B, 0x04, 0x25, 0x28, 0x00, 0x00, 0x00, 0x48, 0x89, 0x45, 0xF8, 0x31, 0xC0, 0xB8, 0x00, 0x00, 0x00, 0x00, 0xE8, 0xD5, 0xFB, 0xFF, 0xFF, 0x48, 0x8D, 0x85, 0x70, 0xFF, 0xFF, 0xFF, 0x48, 0x89, 0xC6, 0xBF, 0xEC, 0x2F, 0x40, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0xE8, 0xE9, 0xDE, 0xFF, 0xFF, 0x48, 0x8D, 0x85, 0x70, 0xFF, 0xFF, 0xFF, 0x48, 0x89, 0xC7, 0xE8, 0xBA, 0xDE, 0xFF, 0xFF, 0x89, 0x85, 0xC4, 0xFE, 0xFF, 0xFF, 0x83, 0xBD, 0xC4, 0xFE, 0xFF, 0xFF, 0x10, 0x74, 0x14, 0xBF, 0xE5, 0x2F, 0x40, 0x00, 0xE8, 0x51, 0xDE, 0xFF, 0xFF, 0xBF, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x57, 0xDE, 0xFF, 0xFF, 0x48, 0xC7, 0x85, 0xC8, 0xFE, 0xFF, 0xFF, 0xF1, 0x2F, 0x40, 0x00, 0x48, 0x8D, 0x95, 0x50, 0xFF, 0xFF, 0xFF, 0x48, 0x8B, 0x85, 0xC8]
length=0x23c
f=open("babyre",mode="rb+")
for i in range(0x23c):
    f.seek(0x272d+i,0)
    new_byte=chr(a[i])
    f.write(new_byte)

最后一段算法有多解,利用回溯搜索算法解出全部可能后

#include 
#include
unsigned char key[17] = "th1s1sth3n1c3k3y";
unsigned char  input[32] = "";

unsigned char byte_604100[31] = {
     
0xBD, 0xAD, 0xB4, 0x84, 0x10, 0x63, 0xB3, 0xE1, 0xC6, 0x84, 0x2D, 0x6F, 0xBA, 0x88, 0x74, 0xC4,
0x90, 0x32, 0xEA, 0x2E, 0xC6, 0x28, 0x65, 0x70, 0xC9, 0x75, 0x78, 0xA0, 0x0B, 0x9F, 0xA6
};
void back_tracking(int row)
{
     
	if (row == 31)
	{
     
		for(int i=0;i<32;i++)
			printf("0x%02x,", input[i]);
		
		system("pause");
	}
	for (int k = 31 - row; k >= 1;)
	{
     
		for (unsigned char a = 0; a < 0xff; a++)
		{
     
			input[k - 1] = a;
			//printf("%x\n", a);
			unsigned char result = (2 * (input[k - 1] ^ 0x13) + 7) ^ ((unsigned __int8)input[k - 1] % 9u + input[k] + 2);
			if (result == byte_604100[k - 1])
			{
     
				//printf("input%d:%x\n", k - 1, a);
				back_tracking(row + 1);

			}
		}
		//back_tracking(row - 1);
		return;

	}
}
int main()
{
     
	input[31] = 0xc4;
	back_tracking(0);
    getchar();
}
	//4d775e0ffe00d4ebb0c06e897af2f51873ee935b86b962ec897c11d00734b2c8

一组一组带到如下脚本里,去AES解密

int main()
{
     
unsigned char key[17] = "th1s1sth3n1c3k3y";
unsigned char input[32] = {
      0x4d,0x77,0x5e,0x0f,0xb3,0x4d,0x99,0xa6,0x8a,0xfa,0x54,0xb3,0x1e,0x96,0x91,0x7c,0x18,0x85,0xf8,0x30,0x5e,0x61,0xba,0x34,0x1c,0xe9,0x84,0x45,0x0b,0x38,0xbe,0xc4 };
	printf("\n");
	for (int i = 31; i >= 0; i--)
	{
     
		for (int j = 0; i / 4 > j; ++j)
		{
     
			input[i] ^= input[j];
		}
	}
	for (int i = 0; i < 32; i++)
	{
     
		printf("%02x", input[i]);
	}
	printf("\n");
	for (int i = 0; i < 16; i++)
	{
     
		printf("%02x", key[i]);
	}
	getchar();
}

最后解到flag

GWHT{th1s_gam3_1s_s0_c00l_and_d}

EasyRe

一共三段加密,第一段是base64,第二段是将数据分为四段重新组合,第三段是将数据进行移位

第三段解密脚本

第一段解密

#include 

int main()
{
     
	char v5;
	char a[100] = {
     0,};
	char b[100] = {
     0,};
	char *v7 = a;
	char *v8 = b;
	char result[] = "EmBmP5Pmn7QcPU4gLYKv5QcMmB3PWHcP5YkPq3=cT6QckkPckoRG";
	for (int j = 0; j < sizeof(result); j++)
	{
     
		for (char i = 0x20; i <= 0x7b; i++)
		{
     
			*v8 = i;
			v5 = *v8;
			if (*v8 <= 0x40 || v5 > 0x5A)
			{
     
				if (v5 <= 0x60 || v5 > 0x7A)
				{
     
					if (v5 <= 0x2F || v5 > 0x39)
						*v7 = v5;
					else
						*v7 = (v5 - 0x30 + 3) % 10 + 0x30;
				}
				else
				{
     
					*v7 = (v5 - 0x61 + 3) % 26 + 0x61;
				}
			}
			else
			{
     
				*v7 = (v5 - 0x41 + 3) % 26 + 0x41;
			}
			if (*v7 == result[j])
			{
     
				++v7;
				++v8;
				printf("%c", v5);
				break;
			}	
		}
	}

将结果分为四组重新拼接

R1dIVHs2NzJjYzQ3NzhhMzhlODBjYjM2Mjk4NzM0MTEzM2VhMn0=

再base64解密得到结果

你可能感兴趣的:(CTF-RE)