签到
文件用Exeinfo PE打开,无壳用ida64位打开
F5跳转到C语言界面,可以发现明文
rc4
无壳,用ida64打开,发现为rc4加密可以直接用动调拿flag,在输入后面下断点按F9后选择动调方式再按F9进入。
输入随便21位字符串,进入后双击Str也就是我们输入的数组,右击选择到Change byte 将v5中的数据粘贴进去。
换完数据之后按F8步过运行,过完加密函数之后,随后发现flag。
Baby c
附件里是一个.h和.c文件,.h文件里定义了一堆宏,用特殊符号代表不同的数据类型和变量名等等,只需要把关键的一些变量名和运算换一下就明白了,就是先异或0x12,然后+1,然后和正确的加密结果进行比较。
写个脚本将过程逆过来。
#include <stdio.h>int main() {unsigned char enc[] = {0x49, 0x56, 0x52, 0x47, 0x55, 0x6a, 0x56, 0x7e, 0x23, 0x57,0x4e, 0x79, 0x23, 0x51, 0x4e, 0x54, 0x67, 0x4e, 0x72, 0x5f,0x74, 0x7d, 0x56, 0x68, 0x74, 0x76, 0x58, 0x70};int len = sizeof(enc) / sizeof(enc[0]);for (int i = 0; i < len; i++) {printf("%c", (enc[i] - 1) ^ 0x12);}return 0;
}
汇编
打开txt文件开头即为将数据储存到某个寄存器内
加密逻辑为后半部分,先进行异或和0x4D后加0x14
有的友友说看不懂怎么办
没关系放到ChatGPT里就能轻松解决
十分友好哈
然后就可以写一个脚本给它逆过来
#include <stdio.h>int main() {unsigned char encrypted[] = {0x3F, 0x35, 0x40, 0x3E, 0x4A, 0x1D, 0x91, 0x26,0x48, 0x36, 0x4C, 0x26, 0x35, 0x38, 0x3A, 0x3C,0x26, 0x1C, 0x4B, 0x26, 0x42, 0x91, 0x34, 0x51,0x38, 0x35, 0x8D, 0x4D, 0x38, 0x91, 0x37, 0x44,0x61};int length = sizeof(encrypted) / sizeof(encrypted[0]);for (int i = 0; i < length; i++) {unsigned char c = encrypted[i];c -= 0x14;c ^= 0x4D;printf("%c", c);}return 0;
}
maze
无壳,ida64直接打开f5找到主函数部分,除去初始化、printf、scanf重要的地方为框出来的,双击进入。
迷宫题找其走出来的路径和表达方式如图1、2部分分别为表达方式和迷宫本身
且由v7、v8那可知迷宫本身为14*14样子的
并且看流程可以指导在不碰到#的情况下到达69即成功
进入2部分
选中数据按shift+e可以发现迷宫是由s.#组成转换成数字类型
然后走一下
进入1部分发现迷宫是wsad类分别为上下左右,对着路线写一下对应字母dsssddwwddssdddsssssdddssssaaaawwwawaasssss
smc
先搜一下smc是什么
参考一下 https://xz.aliyun.com/news/14551
https://www.cnblogs.com/sK07XdAy/p/18213011
同时一般伴随着SMC出现的还有
VirtualProtect一函数为标志
所以这道题肯定要用到动态调试和函数的修复
无壳,ida32打开,shift+f12进入字符串界面找到比较厉害的字符借此进入到关键的函数部分
顺着函数思路点击sub_463E9B即可发现VirtualProtect函数标红
所以断点下在下面那个部分
然后进入动调按f7单步进行
直到发现汇编语言即可发现发现数据不一样了,此时需要IDA重编译功能
选中从头到尾的数据,按u回到字节文本状态
后回到010EC000处即开头按p重新编译
后按f5即可看见函数如图
再写一个解密脚本即可
#include <stdio.h>int main() {unsigned char a[] = {0x1E, 0x72, 0x01, 0x73, 0x23, 0x42, 0x22, 0x43, 0x15, 0x40,0x07, 0x1E, 0x68, 0x29, 0x54, 0x45, 0x5D, 0x29, 0x71, 0x67,0x01, 0x28, 0x5D, 0x10, 0x7A, 0x0E, 0x49, 0x09, 0x64, 0x9C,0x67, 0x44, 0x5E, 0x2A, 0x7D, 0x34, 0x4D, 0x33, 0x46, 0x14,0x64, 0x0B, 0x7D, 0x3B, 0x59, 0x29, 0x06, 0x07};const char* k = "Do_you_know_SMC?";int i;for (i = 0; i < 48; i++) {a[i] ^= k[i % 16];}for (i = 46; i >= 0; i--) {a[i + 1] ^= a[i];}for (i = 0; i < 48; i++) {printf("%c", a[i]);}return 0;
}
游戏高手??
无壳,ida64位打开,找到主函数进入发现一堆系统函数
ai一下发现是类似于贪吃蛇游戏的程序没用,在函数框里面找找找发现okok函数最后printf了一个yes从它开始
其结构大概为检查flag长度,然后在encrypt进行一个加密的过程,最后进行对比
对比的mi数组shift+e将其用16进制表示,去除掉00
发现上面存在i<7部分将mi数组内的数据按照寄存器内高位低位组成8个数据
注意为小端序
enc[0] = 0xf5659330;
enc[1] = 0xb0256707;
enc[2] = 0x550f1326;
enc[3] = 0x576294b2;
enc[4] = 0xad8989bb;
enc[5] = 0x75413ba0;
enc[6] = 0x6d4517e0;
enc[7] = 0xa1a99f25;
点进去encrypt根据异或、加减、位移的特点发现它是tea加密算法
从网上找一个标准的对照脚本修改一下数组和key
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define delta 0x61C88647
void Decrypt(uint32_t* enc, uint32_t* key) {int sum;sum = 32 * delta;uint32_t v1 = enc[0];uint32_t v2 = enc[1];for (int i = 0; i < 32; i++) {sum -= 0x61C88647;v1 += (16 * v2 + key[0]) ^ (v2 + sum) ^ ((v2 >> 5) + key[1]);v2 += (16 * v1 + key[2]) ^ (v1 + sum) ^ ((v1 >> 5) + key[3]);}enc[0] = v1;enc[1] = v2;
}
void print_chars_from_hex(unsigned int hex_value) {int bytes[4];
// 逐个字节从低位到高位获取字符(小端序)bytes[0] = hex_value & 0xff;bytes[1] = (hex_value >> 8) & 0xff;bytes[2] = (hex_value >> 16) & 0xff;bytes[3] = (hex_value >> 24) & 0xff;
// 打印字符for (int i = 0; i < 4; i++) {printf("%c", bytes[i]);}
}
int main() {uint32_t key[4];key[0] = 0x12345678;key[1] = 0xBADF00D;key[2] = 0x5201314;key[3] = 0x87654321;uint32_t enc[8];enc[0] = 0xf5659330;enc[1] = 0xb0256707;enc[2] = 0x550f1326;enc[3] = 0x576294b2;enc[4] = 0xad8989bb;enc[5] = 0x75413ba0;enc[6] = 0x6d4517e0;enc[7] = 0xa1a99f25;for (int i = 0; i < 8; i+=2) {Decrypt(&enc[i], key);}for (int i = 0; i < 8; i++) {printf("enc[%d] = 0x%08x, ", i, enc[i]);}printf("\n");for (int i = 0; i < 8; i++) {print_chars_from_hex(enc[i]);}return 0;
}
rand
无壳,用ida64直接打开,进入到main函数中
观察逻辑发现先在get_key函数中生成一个八位的密钥,然后和输入的flag进行异或,之后就进行比较数据。
但是这里进行比较的数据为v6
点开发现分为两部分一半为v6的前半部分一个是后半部分
v6有一大坨数据而flag只有30位
在观察后发现C4B1是重复的部分,而且去掉这部分结合后正好满足30位
真是可恶
再根据寄存器内数据由低位到高位的先后顺序可以找到数组v6
v6[] = {0xC4, 0x44, 0x85, 0xCE, 0x7B, 0x37, 0xA8, 0xAB, 0xEB, 0x5C,0xA7, 0xC8, 0x0E, 0x13, 0xB1, 0xC4,0xFC, 0x32, 0x81, 0xC5, 0x7E, 0x7C, 0xA6, 0xC4, 0xD6, 0x43, 0x99, 0xD2, 0x7D,0x31}
点入encrypt加密那里发现是一个与刚刚随机数生成的进行异或
然后用C语言写一个用v6数组进行这一过程的脚本
#include <stdio.h>
#include <stdlib.h>
int main() {srand(0x673F026Eu);int key[8] = { 0 };int enc[] = {0xC4, 0x44, 0x85, 0xCE, 0x7B, 0x37, 0xA8, 0xAB, 0xEB, 0x5C,0xA7, 0xC8, 0x0E, 0x13, 0xB1, 0xC4,0xFC, 0x32, 0x81, 0xC5, 0x7E, 0x7C, 0xA6, 0xC4, 0xD6, 0x43, 0x99, 0xD2, 0x7D,0x31};for (int i = 0; i < 8; i++) {key[i] = rand() % 256;}for (int i = 0; i < 30; i++) {printf("%c", enc[i] ^ key[i % 8]);}return 0;
}
但是这个过程在主机上怎么也找不到flag可能要在linux系统下才行
后来知道里面含有随机数,windows系统下和linux系统下生成的不同要在linux系统才行
然后在kali linux下载gcc编译器运行c文件
喜欢香香的吗比如花和茶
无壳,ida32位打开,进入main0函数分析一下程序可以看到前面是许多初始化然后输入加密再进行对比
点进加密的函数可以发现是花指令,这里可以看一下花指令的处理方式 https://www.nssctf.cn/note/set/5217
点进汇编语言,首先对call这行汇编按d转换成数据形式,随后把0E8修改成nop也就是0x90(edit->patch program->change byte)
然后按c修复修改完的这行代码,再将后边两虚线之间的部分也按c修复直至图所示
接下来回到00411980处按p形成函数,按f5即可获得修复好的函数
观察这一函数会发现和之前游戏高手那道简直是姐妹版
再加上文件名为xxtea所以可以查到为xxtea加密方式
题中的加密是标准的在网上找一找xxtea解密的脚本修改一下带入进去即可
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define DELTA 0x61C88647
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[((p&3)^e)&0xff] ^ z)))
void btea(uint32_t* v, int n, const uint32_t key[4])
{uint32_t y, z, sum;unsigned p, rounds, e;if (n > 1){rounds = 6 + 52 / n;sum = 0;z = v[n - 1];while(rounds-->0){sum += DELTA;e = (sum >> 2) & 3;for (p = 0; p < n - 1; p++){y = v[p + 1];z = v[p] += MX;}y = v[0];z = v[n - 1] += MX;}}else if (n < -1){n = -n;rounds = 6 + 52 / n;sum = -rounds * DELTA;y = v[0];do{e = (sum >> 2) & 3;for (p = n - 1; p > 0; p--){z = v[p - 1];y = v[p] -= MX;}z = v[n - 1];y = v[0] -= MX;sum += DELTA;}while (--rounds);}
}
int main() {unsigned char v[32];v[0] = 0x7b;v[1] = 0x4f;v[2] = 0x36;v[3] = 0xDD;v[4] = 0x87;v[5] = 0xEC;v[6] = 0x56;v[7] = 0x3A;v[8] = 0x17;v[9] = 0x50;v[10] = 0x94;v[11] = 0x69;v[12] = 0xA6;v[13] = 0x4E;v[14] = 0x53;v[15] = 0x34;v[16] = 0x59;v[17] = 0xD6;v[18] = 0xD5;v[19] = 0x17;v[20] = 0x64;v[21] = 0xF5;v[22] = 0x2B;v[23] = 9;v[24] = 0x18;v[25] = 0x35;v[26] = 0xE1;v[27] = 0x6E;v[28] = 0xAE;v[29] = 0x6F;v[30] = 0xB4;v[31] = 0xAE;int r = 8;uint32_t k[4];k[0] = 0x1234567;k[1] = 0x89ABCDEF;k[2] = 0xFEDCBA98;k[3] = 0x76543210;btea(((uint32_t*)v),-r,k);for (int i = 0; i < 36; i++) {printf("%c",v[i]);}return 0;
}