CTF · 2024年1月27日

2024春秋杯冬季联赛 upx2023

upx2023

知识点:爆破时间seed,一种简单的映射应对方法,upx标志修改

第一步 脱upx壳

这道题脱壳只需要把exe拖到010里把upx标志由小写改成大写即可。

第二步 程序解读

输入

change

异或比较

第三步 逆向获得flag

std::operator<<<std::char_traits<char>>(&std::cout, Str);
  std::operator>><char>(&std::cin, v7);
  std::string::string(v9, v7);
  change(v8, v9);
  std::string::operator=(v7, v8);
  std::string::~string(v8);
  std::string::~string(v9);

std::string::operator 赋值

if ( std::string::length(v7) != 42 )
  {
    v3 = std::operator<<<std::char_traits<char>>(&std::cout, "len error");

长度42

for ( i = 0; i <= 41; ++i )
  {
    v10 = rand() % 255;
    v4 = std::string::operator[](v7, i);
    if ( (v10 ^ *v4) != v6[i] )
      exit(0);

rand爆破解决

Seed = time(0i64);
srand(Seed);

应该是一个时间戳随机数 我们结合pe文件的时间直接爆破伪随机

Timestamp : 647AA837 (Sat Jun 03 02:40:55 2023)

结合

.rdata:000000000047F008 69 6E 70 75 74 20 79 6F 75 72+Str db 'input your flag'                ; DATA XREF: main+41↑o
.rdata:000000000047F017 A3                            db 0A3h
.rdata:000000000047F018 A8                            db 0A8h
.rdata:000000000047F019 D3                            db 0D3h
.rdata:000000000047F01A C3                            db 0C3h
.rdata:000000000047F01B 66                            db  66h ; f
.rdata:000000000047F01C 6C                            db  6Ch ; l
.rdata:000000000047F01D 61                            db  61h ; a
.rdata:000000000047F01E 67                            db  67h ; g
.rdata:000000000047F01F 7B                            db  7Bh ; {
.rdata:000000000047F020 7D                            db  7Dh ; }
.rdata:000000000047F021 B0                            db 0B0h
.rdata:000000000047F022 FC                            db 0FCh
.rdata:000000000047F023 B9                            db 0B9h
.rdata:000000000047F024 FC                            db 0FCh
.rdata:000000000047F025 A3                            db 0A3h
.rdata:000000000047F026 A9                            db 0A9h
.rdata:000000000047F027 3A                            db  3Ah ; :
.rdata:000000000047F028 20                            db  20h
.rdata:000000000047F029 00                            db    0

对flag{}进行爆破即可

exp如下

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(){
    unsigned int seed;
    int key=0;
    int i =0;
    //1662973302 # 正确的seed
    for(seed = 1662973302;seed<1705929558;seed++){
        srand(seed);
        int right = 1;
        for(i=0;i<=32;i++){
            key = rand() % 255;
            switch (i) {
                case 0:
                    if(key!=0x6f){
                        right = 0;
                    }
                    break;
                case 1:
                    if(key!=0x18){
                        right = 0;
                    }
                    break;

                case 11:
                    if(key!=0xaa){
                        right = 0;
                    }
                    break;
                case 12:
                    if(key!=0x2){
                        right = 0;
                    }
                    break;
                case 32:
                    if(key!=0x9b){
                        right = 0;
                    }
                    break;
                default:
                    break;

        }
            if(right == 0){
                break;
            }
        }
        if(right==1){
            printf("%un",seed);
        }
    }
    return 0;
}

结果:1682145110n

异或对比key直接取

0x09, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0xD9, 0x00, 0x00, 0x00, 0xF6, 0x00, 0x00, 0x00, 
    0x58, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, 
    0x0F, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, 
    0x65, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0xED, 0x00, 0x00, 0x00, 
    0xC4, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x00, 
    0xE5, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, 0xA9, 0x00, 0x00, 0x00, 
    0x31, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0xD7, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 
    0x6C, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x00, 0x00, 
    0xFA, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0xDB, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 
    0xCD, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 
    0x13,0x00,0x00,0x00,0x08

EXP如下

unsigned char data[42] = {
	0x09, 0x63, 0xD9, 0xF6, 0x58, 0xDD, 0x3F, 0x4C, 0x0F, 0x0B, 0x98, 0xC6, 0x65, 0x21, 0x41, 0xED,
	0xC4, 0x0B, 0x3A, 0x7B, 0xE5, 0x75, 0x5D, 0xA9, 0x31, 0x41, 0xD7, 0x52, 0x6C, 0x0A, 0xFA, 0xFD,
	0xFA, 0x84, 0xDB, 0x89, 0xCD, 0x7E, 0x27, 0x85, 0x13, 0x08
	};#这个就是上面直接拿的

	srand(1682145110);
	for (int i = 0; i < 42; i++) {
		c = rand() % 255;
		printf("%c", data[i] ^ c);
	} 
//f{52bgb-281lg00ff-46f7-ca009c8e}a381-b7191

映射动调解决

假设一个char:flag{1234567890qwertyuiopAsdFGhjkLzxcvbnm}

动调结果:

得到映射关系

根据映射关系得到输入的flag

f{48wypFkcmlg13579qetuoAdGjLxvn}a260rishzb

exp如下

映射

a = 'flag{1234567890qwertyuiopAsdFGhjkLzxcvbnm}'
b = 'f{48wypFkcmlg13579qetuoAdGjLxvn}a260rishzb'
input_set = []
for i in b:
      input_set.append(a.index(i))

print(input_set) # 得到换位的顺序

末初大佬队的exp更简便:

#include <stdio.h>
int main(){
char res[] = "f{52bgb-281lg00ff-46f7-ca009c8e}a381-b7191";

	char s1[] = "flag{1234567890QWERTYUIOPASDFGHJKLZXCVBNM}";
	char r1[] = "f{48WYPFKCMlg13579QETUOADGJLXVN}a260RISHZB";

	
	for (int i = 0; i < 42; i++) {
		for (int j = 0; j < 42; j++) {
			if (s1[i] == r1[j]) {
				printf("%c", res[j]);
			}
		}
	} 
}

flag{0305f8f2-14b6-fg7b-bc7a-010299c881e1}

动调演示视频

flag{1234567890qwertyuiopAsdFGhjkLzxcvbnm}

https://www.bilibili.com/video/BV18w411j7ku/?spm_id_from=333.999.0.0&vd_source=c2cbf1fb7b27180057fbc666e94417ad