首页 > 其他分享 >i春秋夏令营Reverse

i春秋夏令营Reverse

时间:2024-07-20 22:29:12浏览次数:14  
标签:00 enc Reverse 春秋 data range key 256 夏令营

前言:第一次参加,只写了前两个,最后一个赛后复现。写的尽量详细一点,希望大家都能看懂

snake

运行贪吃蛇游戏

进行查壳:

解包一下:

在解包的文件中找到与文件名相同的.pyc文件\snake\snake.exe_extracted\snack.pyc

老本的pyinstxtractor.py可能生成的不是.pyc文件,需要用010补一下文件头
55 0D 0D 0A 00 00 00 00 00 00 00 00 00 00 00 00,再将末尾改为.pyc就可以使用工具了

snake.pyc包含了游戏逻辑与加密算法,简单筛选一下保留加密算法部分(游戏逻辑显示大于9999分就可以直接获得flag,so游戏佬除外)

#魔改RC4
import random
import key
 
def initialize(key):
     key_length = len(key)
     S = list(range(256))
     j = 0
     for i in range(256):
         j = (j + S[i] + key[i % key_length]) % 256
         S[i] = S[j]
         S[j] = S[i]
     return S
  
def generate_key_stream(S, length):
     i = 0
     j = 0
     key_stream = []
     for _ in range(length):
         i = (i + 1) % 256
         j = (j + S[i]) % 256
         S[i] = S[j]
         S[j] = S[i]
         key_stream.append(S[(S[i] + S[j]) % 256])
     return key_stream
 
def decrypt(data, key):
    S = initialize(key)
    key_stream = generate_key_stream(S, len(data))
    decrypted_data = None((lambda .0 = None: [ i ^ data[i] ^ key_stream[i] for i in .0 ])(range(len(data))))
    return decrypted_data
 
key_bytes = bytes((lambda .0: [ ord(char) for char in .0 ])(key.xor_key))
data = [101,97,39,125,218,172,205,3,235,195,72,125,89,130,103,213,120,227,193,67,174,71,162,248,244,12,238,92,160,203,185,155]
decrypted_data = decrypt(bytes(data), key_bytes) 

在解包的PYZ-00.pyz_extracted中找一下key.pyc,有的pyinstxtractor.py得到的文件夹为空,可以换一个版本进行解决,反编译得到key
推荐几个反编译pyc的网站:
python反编译 - 在线工具 (tool.lu)
在线Python pyc文件编译与反编译
pyc反编译 - 工具匠

exp:

def rc4_decrypt(key, length):
    S = list(range(256))
    j = 0
    for i in range(256):
        j = (j + S[i] + key[i % len(key)]) % 256
        S[i], S[j] = S[j], S[i]
 
    i = j = 0
    text = []
    for _ in range(length):
        i = (i + 1) % 256
        j = (j + S[i]) % 256
        S[i], S[j] = S[j], S[i]
        text.append(S[(S[i] + S[j]) % 256])
    return text
 
key = b'V3rY_v3Ry_Ez'
data = [101, 97, 39, 125, 218, 172, 205, 3, 235, 195, 72, 125, 89, 130, 103, 213, 120, 227, 193, 67, 174, 71, 162, 248, 244, 12, 238, 92, 160, 203, 185, 155]
text = rc4_decrypt(key, len(data))
flag = ''
for i in range(len(data)):
    flag += chr(data[i] ^ text[i] ^ i)
print(flag)

得到flag{KMLTz3lT_MePUDa7A_P5LpzCBT}

HardSignin

无法运行程序,直接查壳——upx,直接使用工具脱不了,应该是被魔改了,010查看一下


使用另外一个查壳工具发现改成了vmp,修改回来(共三处UPX1,UPX2,UPX!)


使用UPX Unpacker或者指令upx -d HardSignin.exe都可以
使用ida32打开发现没有main函数

对_main进行交叉引用Upo.text:loc_401029mov dword ptr [ebp-4], offset _main,发现四个TLS回调函数,但是存在基础花指令修改一下

第一处:(右键->Patching->change byte->E2改为90->快捷键C转为汇编代码)

第二处:(右键->Patching->change byte->9A改为90->快捷键C转为汇编代码)

第三处:(右键->Patching->change byte->C2改为90->快捷键C转为汇编代码)

TlsCallback_0,TlsCallback_1,TlsCallback_2后按快捷键P转换为函数
TlsCallback_0函数存在一点问题,字节异或0x66

由于是可以运算,我们直接写exp,shift+F2打开编辑窗口,编写脚本:

from ida_bytes import *
addr = 0x00401890
for i in range(170):
    patch_byte(addr + i,get_wide_byte(addr + i)^0x66)

C+P转换得到主函数main:

分析encrypt函数:

其余密文的脚本(由于XTEA加密是四字节所以64//4):

from ida_bytes import *
from idaapi import *
addr = 0x00404000
enc = []
for i in range(64//4):
    enc.append(get_dword(addr + i * 4))
print(enc)
#[3036486489, 3653154923, 3598177203, 408905200, 1396350368, 645614189, 1318861428, 3625534240, 3046501746, 1445070236, 2433841867, 213678751, 3463276874, 699118653, 845347425, 3058494644]

两个加密的key都是随机生成的,交叉索引找到TLS1和TLS2



srand(0x114514u)是mz_base64的随机种子
srand(0x1919810u)是mz_RC4和mz_XTEA的随机数种子
1.解密mz_XTEA:

#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
#include<string.h>
 
void XTEA_decrypt(uint32_t* enc, uint32_t* key);
 
int main() {
    uint8_t RC4_key[16] = { 0 };
    char XTEA_key[16] = { 0 };
    uint32_t enc[] = { 3036486489, 3653154923, 3598177203, 408905200, 1396350368, 645614189, 1318861428, 3625534240, 3046501746, 1445070236, 2433841867, 213678751, 3463276874, 699118653, 845347425, 3058494644 };
    srand(0x1919810u);
    for (int i = 0; ; ++i){
        if (i >= 16)
            break;
        RC4_key[i] = rand() % 255;
        XTEA_key[i] = rand() % 255;
    }
    XTEA_decrypt(enc, (uint32_t*)XTEA_key);//指针强转
    //uint8_t* temp = (uint8_t*)enc;
    for (int i = 0; i < 16; i++) {
        //printf("%d, ", temp[i]);
        printf("%d, ", RC4_key[i]);
    }
    return 0;
}
void XTEA_decrypt(uint32_t* enc, uint32_t* XTEA_key) {
    uint32_t v7, v6, v5;
    for (int i = 0; i < 16; i += 2){
        v7 = enc[i];
        v6 = enc[i + 1];
        v5 = 0x9E3779B9 * 0x64;
        for (int j = 0; j < 0x64; ++j)
        {
            v6 -= (XTEA_key[(v5 >> 11) & 3] + v5) ^ (v7 + ((v7 >> 5) ^ (16 * v7)));
            v5 -= 0x9E3779B9;
            v7 -= (XTEA_key[v5 & 3] + v5) ^ (v6 + ((v6 >> 5) ^ (16 * v6)));
        }
        enc[i] = v7;
        enc[i + 1] = v6;
    }
}

得到:188, 237, 0, 123, 134, 244, 22, 147, 149, 249, 135, 220, 103, 168, 162, 127, 77, 226, 98, 159, 123, 52, 174, 233, 69, 3, 126, 53, 66, 208, 139, 112, 240, 251, 46, 199, 221, 233, 185, 115, 227, 204, 26, 117, 173, 220, 253, 20, 168, 200, 69, 22, 49, 110, 42, 8, 44, 15, 29, 159, 7, 186, 213, 239

2.解密mz_RC4

def rc4_decrypt(ciphertext, key):
    S = list(range(256))
    j = 0
    for i in range(256):
        j = (j + S[i] + key[i % len(key)]) % 256
        S[i], S[j] = S[j], S[i]
 
    i = j = 0
    plaintext = []
    for byte in ciphertext:
        i = (i + 1) % 256
        j = (j + S[i]) % 256
        S[i], S[j] = S[j], S[i]
        k = S[(S[i] + S[j]) % 256]
        plaintext.append(byte ^ k)
 
    return bytes(plaintext)
enc = [188, 237, 0, 123, 134, 244, 22, 147, 149, 249, 135, 220, 103, 168, 162, 127, 77, 226, 98, 159, 123, 52, 174, 233,
       69, 3, 126, 53, 66, 208, 139, 112, 240, 251, 46, 199, 221, 233, 185, 115, 227, 204, 26, 117, 173, 220, 253, 20,
       168, 200, 69, 22, 49, 110, 42, 8, 44, 15, 29, 159, 7, 186, 213, 239]
RC4_key = [118, 137, 51, 73, 25, 19, 195, 199, 173, 216, 228, 104, 252, 72, 4, 188]
 
decrypted_data = rc4_decrypt(enc, RC4_key)
print(decrypted_data)
#b'C+vFCnHRGPghbmyQMXvFMRNd7fNCG8jcU+jcbnjRJTj2GTCOGUvgtOS0CTge7fNs'

3.解密mz_base64:
求变表

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
 
void swap(char* a, char* b) {
    char temp = *a;
    *a = *b;
    *b = temp;
}
 
int main() {
    char base64table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    int v6, v4;
    srand(0x114514u);
    for (int i = 0; i < 100; ++i) {
        v6 = rand() % 64;
        v4 = rand() % 64;
        swap(&base64table[v6], &base64table[v4]);
    }
    printf("%s\n", base64table);
    return 0;
}
//4yZRiNP8LoK/GSA5ElWkUjXtJCz7bMYcuFfpm6+hV0rxeHIdwv32QOTnqg1BDsa9

解密:

import base64
text1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
text2 = '4yZRiNP8LoK/GSA5ElWkUjXtJCz7bMYcuFfpm6+hV0rxeHIdwv32QOTnqg1BDsa9'
enc = 'C+vFCnHRGPghbmyQMXvFMRNd7fNCG8jcU+jcbnjRJTj2GTCOGUvgtOS0CTge7fNs'
 
decoded_bytes = base64.b64decode(enc.translate(str.maketrans(text2, text1)))
 
print(decoded_bytes.decode("utf-8"))

flag{C0ngr@tulat1on!Y0u_Re_suCces3fu1Ly_Signln!}

bedtea

运行代码,无壳直接用IDA64打开,一个C++程序

main函数还是比较复杂的

逻辑:flag->魔改TEA加密->二叉树倒叙->异或0x33->enc

难点在于密文和密钥都是隐藏的,需要进行动态调试,但是动调调试会出现不正确的密文,需要修改检测动态调试的值,在此之前看一下魔改的TEA是怎么样的吧!


本地动态调试就可以,在此下断点

发现RAX寄存器为1,修改一下

去sub_401E80()函数观察xmmword_408040(TEA_key)的变化,F9运行,两个地址来回断


记录一下:0x03050D08,0x15223759,0x90E9179262

密文地址:

写脚本提取一下(为了方便起见直接倒叙加异或):

from idaapi import *
import ida_bytes
enc = []
addr = 0x0000000000405080
for i in range(24):
    enc.append(ida_bytes.get_word(addr + i * 2))
enc.reverse()
dec = [x ^ 0x33 for x in enc]
print(dec)

[211, 109, 186, 193, 54, 101, 42, 137, 120, 145, 245, 49, 250, 190, 194, 49, 144, 12, 68, 67, 212, 174, 66, 69]

exp:(本来想写个自动化脚本,但是时间成本太高了,一共加密三大轮回,替换都比解决bug快,难受)

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
 
int main() {
    uint8_t enc[] = { 211, 109, 186, 193, 54, 101, 42, 137 };
                    //{ 120, 145, 245, 49, 250, 190, 194, 49 }
                    //{ 144, 12, 68, 67, 212, 174, 66, 69}
    uint32_t* denc = (uint32_t*)enc;
    uint32_t v15 = denc[0];
    uint32_t v13 = denc[1];
    uint32_t v14 = 0x9E3449B8 * 22;
    //key1[] = {0x03, 0x05, 0x0D, 0x08}
    //key2[] = {0x15, 0x22, 0x37, 0x59}
    //key3[] = {0x90, 0xE9, 0x179, 0x262};
    for (int i = 0; i < 22; i++) {
        v13 -= (v14 + v15) ^ (0x0D + (v15 >> 4)) ^ (0x08 + 32 * v15);
        v15 -= (v14 + v13) ^ (0x05 + (v13 >> 4)) ^ (0x03 + 32 * v13);
        v14 -= 0x9E3449B8;
    }
    denc[0] = v15;
    denc[1] = v13;
    printf("%s\n", enc);
    return 0;
}

得到:

flag{y0ux戸1??DC援BE烫烫嚈`榾

_reallyl烫烫?騡待?

1ke_te@}烫烫獞胇X鷞

手动拼接:flag{y0u_reallyl1ke_te@}(flag{y0ux_reallyl1ke_te@}不对一下就知道了,在提交答案时还设置了坑)

标签:00,enc,Reverse,春秋,data,range,key,256,夏令营
From: https://www.cnblogs.com/N1ng/p/18313909

相关文章

  • Datawhale AI 夏令营——CV图像竞赛(Deepfake攻防)——Task3学习笔记
        这一篇是在数据增强的方向上发力,尝试提升模型的表现。        数据增强的目的是通过人工方式增加训练数据的多样性,从而提高模型的泛化能力,使其能够在未见过的数据上表现得更好。对于图像而言,数据增强包括例如视角、光照、遮挡等情况,使得模型能够学习到......
  • Datawhale Al夏令营——Transformer架构
    Transformer:这个模型架构就是摒弃了所有的循环结构,完全依赖于注意力机制对源语言序列和目标语言序列全局依赖的建模对于循环神经网络来说,上下文的语义依赖是通过维护循环单元中的隐状态实现的。在编码过程中,每一个时间步的输入建模都涉及到对隐藏状态的修改。随着序列长度的增加,......
  • DatawhaleAI夏令营 机器学习方向 学习笔记
    电力需求预测挑战赛理解赛题【训练时序预测模型助力电力需求预测赛题任务给定多个房屋对应电力消耗历史N天的相关序列数据等信息,预测房屋对应电力的消耗。赛题数据赛题数据由训练集和测试集组成,为了保证比赛的公平性,将每日日期进行脱敏,用1-N进行标识。即1为数据集最近一天,......
  • TASK 3 Datawhale AI 夏令营
    \(transformer\)解决任务1.特点摒弃了循环结构,通过自注意力机制衡量上下文单词的重要程度说人话就是联系前后单词对于该单词的影响来完成本单词的翻译2.运行逻辑在运行前,由于摒弃了循环结构,我们需要在词语中嵌入位置编码来构建单词的向量表示,模型利用每个词语的位置与维度构......
  • Datawhale AI 夏令营——电力需求挑战赛——Task3学习笔记
        这一期学习进阶的特征提取与分析,构建深度学习方案,拿下更高分数,冲冲冲。项目链接:‌​​‬​‍​​​‌​‬‬⁠​​⁠​⁠​​​​⁠​​‍​​‍​​‌⁠‬​⁠​⁠‍‌​‌​​‍​Task3:尝试使用深度学习方案-飞书云文档(feishu.cn)    前两期介绍了......
  • Datawhale AI 夏令营 task2语言包陷入困境
     一、了解机器翻译在运行task1时,我仅仅只是按照教程一步步走下去,不理解每一步的意义,也不懂什么叫做机器翻译。于是在task2中碰了壁。1.机器翻译的含义机器翻译(MT)是自然语言处理领域的一个重要分支,其目标是将一种语言的文本自动转换为另一种语言的文本。机器翻译的发展经历......
  • 2024夏令营提高1模考0718模拟赛(提高1)补题报告
    2024夏令营提高1模考0718模拟赛(提高1)补题报告$$0718模拟赛(提高1)\\补题报告\2024年7月18日\by\\\唐一潇$$一、做题情况第一题比赛$100/100$,赛后通过第二题比赛$0/100$,赛后通过第三题比赛$0/100$,赛后通过第四题比赛$0/100$,赛后通过比......
  • Datawhale AI 夏令营——CPU部署大模型(LLM天池挑战赛)——Task2与3学习笔记
        Task2的任务是组队+寻找灵感,这里不作阐述;Task3的任务是实现RAG应用,阅读文档并观看卢哥的直播后,结合个人经验做个分享。    运行大语言模型,对LLM使用的加深,我们发现,在使用过程中,大模型会有很多幻觉出现。为了解决幻觉,科研人员提出了各种各样的方案......
  • 【DataWhale AI夏令营】--Task 2
    目录1.赛题任务2.baseline代码(1)第一步:导入所需模块(2)探索性数据分析(EDA)(3)数据可视化(4)合并训练数据和测试数据,进行一些数据预处理操作,然后重新切分出训练集和测试集(5)模型训练与测试集预测3.运行结果优化方向优化代码优化总结优化要点总结1.赛题任务使用进阶的机......
  • DataWhale AI夏令营 电力预测赛Day2
    LightGBM支持高效LightGBM(LightGradientBoostingMachine)是一个实现GBDT算法的框架,支持高效率的并行训练,并且具有更快的训练速度、更低的内存消耗、更好的准确率、支持分布式,可以快速处理海量数据等优点。LightGBM框架中还包括随机森林和逻辑回归等模型。通常应用......