目录
我的upx -d怎么坏了
动调脱upx壳:
babypython
BadCoffee
ob混淆:
我的upx -d怎么坏了
打开附件,发现是upx壳,应该是修改了区段名或者特征码
但是修改过还是不对.....(哭.jpg)应该还是改了其他
好学长告诉我直接动态调试脱壳
动调脱upx壳:
在吾爱破解版OD里面打开,
打开位置可以看到上面一点就有popad指令,在上面下断点
F9程序运行到下一个断点
1 处是循环处理栈空间, 2 处有个大跳转,从0x41C131跳转到0x4012D0处,可能是程序的ope入口,F7跟进0x4012D0,在此处用插件dump程序出来
直接点脱壳保存,就可以得到脱壳后的程序
没显示壳了,放入到ida中,迷宫题
int sub_40143C()
{char Str[100]; // [esp+1Ch] [ebp-74h] BYREFint len; // [esp+80h] [ebp-10h]int v3; // [esp+84h] [ebp-Ch]int v4; // [esp+88h] [ebp-8h]int i; // [esp+8Ch] [ebp-4h]sub_401B10();printf("Please input your flag: ");scanf("%s", Str);len = strlen(Str);v4 = 1;v3 = 1;for ( i = 0; i < len; ++i ){switch ( Str[i] ){case 'U': // 上--v4;break;case 'D': // 下++v4;break;case 'L': // 左--v3;break;case 'R': // 右++v3;break;}if ( sub_401410(v4, v3) ) // 迷宫图break;if ( aS0000000000000[15 * v4 + v3] == 35 ) // 走合适路线是值最终为35{printf("You are right!\nflag is flag{md5(your put)}");return 0;}}puts(Buffer);return 0;
}
推荐一位学长的博客,自动走迷宫脚本(膜拜大佬.jpg):(124条消息) C语言实现自动走迷宫 自动输出迷宫路径_OrientalGlass的博客-CSDN博客
下面是引用的博客代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <Windows.h>
// 枚举一些关键常量,可以根据迷宫的不同而修改
enum state
{start = 'S', end = '#', road = '0', wall = '*', visited = '1', successPath = '%', currentPosition = '@'
}State;
//路径操作符枚举
enum operate {up = 'U', right = 'R', down = 'D', left = 'L'
}Operate;
//保存路径
struct
{int len;unsigned char arr[1000];
}Path;
//输入路径
void inputPath(unsigned char op)
{Path.arr[Path.len] = op;Path.len++;
}
//输出路径
void printPath()
{printf("\nPath:");while (Path.len > 0){Path.len--;putchar(Path.arr[Path.len]);}printf("\n");
}
//判断是否在迷宫范围内以及是否可以走这一步
bool isLegal(int x, int y, int row, int col, unsigned char* p)
{if (x >= 0 && y >= 0)if (x < row && y < col)return (p[x * col + y] == road || p[x * col + y] == end);return false;
}
//输入迷宫图
//支持以矩阵形式输入,也可以输入一整行,自动处理换行符,直到读取到整个迷宫图为止
void inputMaze(unsigned char* p, int row, int col)
{unsigned char ch;printf("请输入迷宫图:\n");for (int i = 0; i < row * col; i++){if ((ch = getchar()) != '\n')p[i] = ch;else--i;}}
//打印迷宫图
void printMaze(unsigned char* p, int row, int col) {printf("\n迷宫图如下:\n");for (int i = 0; i < row; i++){for (int j = 0; j < col; j++)printf("%c", p[i * col + j]);printf("\n");}}
//走迷宫
//递归查询,这里由于递归是倒序输出路径,所以需要一个倒序操作
bool walkMaze(int row, int col, unsigned char* p, int x, int y)
{int pos = x * col + y; //当前位置if (p[pos] == end) //到达终点return true;if (isLegal(x - 1, y, row, col, p)) //上{//printMaze(p,row,col); //如果需要可以逐步输出迷宫图p[pos] = visited; //设置访问标识,防止无限递归if (walkMaze(row, col, p, x - 1, y)) //该路径可行,输出操作符{inputPath(up);p[pos] = successPath; //用于显示该路径return true;}}if (isLegal(x, y + 1, row, col, p)) //右{//printMaze(p,row,col);p[pos] = visited;if (walkMaze(row, col, p, x, y + 1)){inputPath(right);p[pos] = successPath;return true;}}if (isLegal(x + 1, y, row, col, p)) //下{//printMaze(p,row,col);p[pos] = visited;if (walkMaze(row, col, p, x + 1, y)){inputPath(down);p[x * col + y] = successPath;return true;}}if (isLegal(x, y - 1, row, col, p)) //左{//printMaze(p,row,col);p[pos] = visited;if (walkMaze(row, col, p, x, y - 1)){inputPath(left);p[pos] = successPath;return true;}}p[pos] = visited;return false; //无路可走,该条路径不行
}//自动寻找起点,可以自行选择是否调用
void findStart(unsigned char* p, int row, int col, int* x, int* y)
{for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){if (p[i * col + j] == start){*x = i;*y = j;return;}}}
}int main()
{int row = 15, col = 15, x = 1, y = 1; //行和列,起点坐标unsigned char* Maze = (unsigned char*)malloc(row * col); //分配空间inputMaze(Maze, row, col); //输入迷宫printMaze(Maze, row, col); //打印迷宫walkMaze(row, col, Maze, x, y); //走迷宫Maze[x * col + y] = start; //矫正起点字符printMaze(Maze, row, col); //打印迷宫printPath(); //打印路径free(Maze); //释放空间system("pause");return 0;
}
或者手动走迷宫,得到最后的结果是 RRRDRRURRRRRRDDDDRDDD
32位小写md5加密即为flag
babypython
下载附件,是python字节码,有很多混淆的无用代码,尝试问chatgpt还原源码
下面是程序有效的代码思路
定义flag,并将flag的每个字符异或8
import timeit
flag = '************************************'
value = ''
output = ''
i = 0while i < len(flag):temp = flag[i] ^ 8value += chr(ord(temp) ^ 8)i += 1
将flag每个字符加3
for i in range(len(flag)):temp = flag[i]temp = chr(ord(temp) + 3)output += temp
将字符串进行base64加密,切片,即将加密后的base64密文反转倒序
import base64output = base64.encode(output.encode())
obfuscated_output = output.decode()obfuscated_output = obfuscated_output[:-1]
将字符串中的g替换成1,H替换成3,W替换成9
obfuscated_output = obfuscated_output.replace('g', '1')
obfuscated_output = obfuscated_output.replace('H', '3')
obfuscated_output = obfuscated_output.replace('W', '9')
invalid_variable = len(obfuscated_output) * 5# 第二个部分
print(obfuscated_output)
将txt文本末尾的加密变换后的字符串逆序,1替换为g,3替换为H,9替换为W,进行base64解密
得到解密后的字符串qglrv@onmlqpA>qmq>mBo3A?Bn<lppA@;lp4nx
写脚本解密,拿到flag:flag{5dcbafe63fbf3b7d8647c1aee650ae9c}
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(){int i;char str[]="qglrv@onmlqpA>qmq>mBo3A?Bn<lppA@;lp4nx";for(i=0;i<strlen(str);i++){str[i]-=3;str[i]^=8;}printf("%s",str);return 0;
}
BadCoffee
下载附件,是js 文件,很多代码,好学长指导,知道是ob混淆
ob混淆:
开头定义了一个大数组,然后对这个大数组里的内容进行位移,再定义一个解密函数。后面大部分的值都调用了这个解密函数,以达到混淆的效果。
这种代码即为ob混淆,不仅变量名混淆了,运行逻辑等也高度混淆,难以理解
对象属性名称替换:混淆工具会将代码中的对象属性名称替换为无意义的名称。例如,将属性名从可读性高的名称(如 "name")替换为随机生成的字符串(如 "_0x1a2b3c")。这使得代码难以理解和分析。
属性访问转换:混淆工具可能会将直接的属性访问(例如
obj.property
)转换为通过字符串进行间接访问的形式(例如obj["property"]
)。这增加了代码的复杂性,使属性访问变得不直观。属性重排序:混淆工具可能会对对象的属性进行重新排序,使属性的顺序变得混乱和不可预测。这增加了代码的困惑性,使属性的逻辑关系更加难以理解。
属性值加密:混淆工具可能会对对象的属性值进行加密或编码,以防止直接获取属性值。这可以使用各种加密算法或编码方案来实现。
对象引用混淆:混淆工具可能会修改对象的引用方式,使对象的引用变得复杂和不明显。例如,将对象的引用存储在数组、函数调用或其他对象中,增加代码的混乱性。
下面是一个示例代码:
var _0x1a2b = ['\x48\x65\x6C\x6C\x6F', '\x57\x6F\x72\x6C\x64', '\x63\x6F\x6E\x73\x6F\x6C\x65', '\x6C\x6F\x67'];//即大数组
//_0x1a2b 是一个包含随机字符串的数组,'\x48\x65\x6C\x6C\x6F' 对应替代属性名 'Hello'
var _0x3c4d = {};
_0x3c4d[_0x1a2b[0x0]] = 'Hello';//偏移
_0x3c4d[_0x1a2b[0x1]] = 'World';//:属性访问使用数组索引来间接访问属性,_0x3c4d[_0x1a2b[0x0]] 表示访问属性 'Hello
_0x3c4d[_0x1a2b[0x2]] = function (_0x24e2) {console[_0x1a2b[0x3]](_0x24e2);
};_0x3c4d[_0x1a2b[0x2]](_0x3c4d[_0x1a2b[0x0]] + ' ' + _0x3c4d[_0x1a2b[0x1]]);//后面都调用解密函数
具体参考这篇文章:(124条消息) ob混淆解密在线工具_在线解ob混淆_滕青山ᅠ的博客-CSDN博客和这篇文章:(124条消息) 爬虫反混淆入门--JS混淆之ob混淆_阿J~的博客-CSDN博客
推荐一个在线工具解密ob混淆:解混淆测试版 (yuanrenxue.cn) (这个在线工具使用火狐浏览器无法使用,可能是我的浏览器问题)
下面是优化后的代码:
function xxx(_0x53b7bb, _0x590286) {return _0x53b7bb ^ _0x590286;
}function enc(_0x4bda4c) {var _0x8ff1dd = [],_0x6aca75 = [233, 129, 127, 238, 145, 144, 11, 43, 87, 134, 243, 158, 197, 216, 111, 136, 152, 29, 204, 31, 26, 228, 39, 148, 215, 220, 90, 76, 251, 57, 183, 184, 150, 157, 156, 176, 13, 41, 30, 86, 244, 8];for (let _0x7bc200 = 0; _0x7bc200 < 42; _0x7bc200++) {_0x8ff1dd[_0x7bc200] = xxx(_0x6aca75['at'](_0x7bc200), _0x4bda4c["charAt"](_0x7bc200)['charCodeAt']());}for (let _0x4f674a = 0; _0x4f674a < 42; _0x4f674a++) {_0x8ff1dd[_0x4f674a] = xxx(_0x8ff1dd['at'](_0x4f674a), _0x6aca75['at'](41 - _0x4f674a));}console["log"](_0x8ff1dd);return _0x8ff1dd;
}function fff() {var _0xe4960c = "flag{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}",_0x55dae6 = enc(_0xe4960c),_0xbb5ecd = [135, 25, 72, 151, 195, 212, 228, 212, 250, 101, 39, 77, 163, 77, 70, 167, 119, 184, 7, 77, 144, 154, 93, 10, 185, 48, 179, 77, 71, 163, 67, 61, 113, 156, 196, 136, 239, 241, 128, 93, 84, 156];for (let _0x37df9d = 0; _0x37df9d < 42; _0x37df9d++) {if (_0x55dae6['at'](_0x37df9d) != _0xbb5ecd['at'](_0x37df9d)) {console["log"]("Error");return;}}console["log"]("YES");return;
}fff();
也可以尝试自己修改变量名和函数名进一步优化 ,优化后稍微好看一点
function xor(a,b) {return a ^b;
}function enc(flag) {var Str3 = [],Str2 = [233, 129, 127, 238, 145, 144, 11, 43, 87, 134, 243, 158, 197, 216, 111, 136, 152, 29, 204, 31, 26, 228, 39, 148, 215, 220, 90, 76, 251, 57, 183, 184, 150, 157, 156, 176, 13, 41, 30, 86, 244, 8];for (letj = 0;j < 42;j++) {Str3[_0x7bc200] = xor(Str2['at'](_0x7bc200), flag["charAt"](_0x7bc200)['charCodeAt']());}for (let k = 0; k < 42; k++) {Str3[k] = xor(Str3['at'](k), Str2['at'](41 - k));}console["log"](Str3);return Str3;
}function fff() {varflag = "flag{xxxxxxxxxxxxxxxxxxxxxxxxxx}",result = enc(flag),Str = [135, 25, 72, 151, 195, 212, 228, 212, 250, 101, 39, 77, 163, 77, 70, 167, 119, 184, 7, 77, 144, 154, 93, 10, 185, 48, 179, 77, 71, 163, 67, 61, 113, 156, 196, 136, 239, 241, 128, 93, 84, 156];for (let i = 0; i < 42; i++) {if (result['at'](i) != Str['at'](i)) {console["log"]("Error");return;}}console["log"]("YES");return;
}fff();
函数的大致思路是flag^str2^str2的反转字符串=str,写脚本解密:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(){char data[]={135, 25, 72, 151, 195, 212, 228, 212, 250, 101, 39, 77, 163, 77, 70, 167, 119, 184, 7, 77, 144, 154, 93, 10, 185, 48, 179, 77, 71, 163, 67, 61, 113, 156, 196, 136, 239, 241, 128, 93, 84, 156};char Buffer[]={233, 129, 127, 238, 145, 144, 11, 43, 87, 134, 243, 158, 197, 216, 111, 136, 152, 29, 204, 31, 26, 228, 39, 148, 215, 220, 90, 76, 251, 57, 183, 184, 150, 157, 156, 176, 13, 41, 30, 86, 244, 8};char flag[100];
int i;
for(i=0;i<42;i++){flag[i]=data[i]^Buffer[i]^Buffer[41-i];printf("%c",flag[i]);
}return 0;
}
未完待续...