目录
我的upx -d怎么坏了
动调脱upx壳:
babypython
BadCoffee
ob混淆:
打开附件,发现是upx壳,应该是修改了区段名或者特征码
但是修改过还是不对.....(哭.jpg)应该还是改了其他
好学长告诉我直接动态调试脱壳
在吾爱破解版OD里面打开,
打开位置可以看到上面一点就有popad指令,在上面下断点
F9程序运行到下一个断点
1 处是循环处理栈空间, 2 处有个大跳转,从0x41C131跳转到0x4012D0处,可能是程序的ope入口,F7跟进0x4012D0,在此处用插件dump程序出来
直接点脱壳保存,就可以得到脱壳后的程序
没显示壳了,放入到ida中,迷宫题
int sub_40143C()
{
char Str[100]; // [esp+1Ch] [ebp-74h] BYREF
int 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
#include
#include
#include
// 枚举一些关键常量,可以根据迷宫的不同而修改
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
下载附件,是python字节码,有很多混淆的无用代码,尝试问chatgpt还原源码
下面是程序有效的代码思路
定义flag,并将flag的每个字符异或8
import timeit
flag = '************************************'
value = ''
output = ''
i = 0
while i < len(flag):
temp = flag[i] ^ 8
value += 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 base64
output = 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
写脚本解密,拿到flag:flag{5dcbafe63fbf3b7d8647c1aee650ae9c}
#include
#include
#include
int main(){
int i;
char str[]="qglrv@onmlqpA>qmq>mBo3A?Bn
下载附件,是js 文件,很多代码,好学长指导,知道是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
#include
#include
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;
}
未完待续...