吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2078|回复: 35
上一主题 下一主题
收起左侧

[分享] 胡思乱想日记和豆包使用体验

[复制链接]
跳转到指定楼层
楼主
小菜鸟一枚 发表于 2026-8-29 17:02 回帖奖励

想不到标题,就是一个学破解的菜鸟生活压力、工作压力下发疯前的胡言乱语,算分享吧吧

一、豆包:用 c 语言写一个入门级 reserveme 给我

1.得到了如下的代码:

#include <stdio.h>
#include <string.h>

int check_password(const char* input)
{
    // 正确密码:hello123
    char real_pwd[] = "hello123";
    if (strlen(input) != strlen(real_pwd))
    {
        return 0;
    }

    for (int i = 0; input[i] != '\0'; i++)
    {
        // 简单异或混淆,稍微增加一点逆向难度(入门级别)
        if( (input[i] ^ 0x01) != (real_pwd[i] ^ 0x01) )
        {
            return 0;
        }
    }
    return 1;
}

int main()
{
    char user_input[32];
    printf("Please input password: ");
    scanf("%31s", user_input);

    if (check_password(user_input))
    {
        printf("Success! You cracked this reverseme.\n");
    }
    else
    {
        printf("Wrong password!\n");
    }
    return 0;
}

2.下载一个dev c++工具吧,编译下,选64位release试试,来了一个exe,运行一下,随便输入一个1,输出错误了。

3.让我对加解密感兴趣的似乎就是这样简简单单的代码吧,一段输入,走向不同的分支,得到不一样的结果,便是吸引我的地方吧。哦,似乎不对,我是从脱壳开始的,看到了吾爱破解论坛的入门培训课程,似乎听不懂,最后又去看小生我怕怕的脱壳教程吧,每次跟着教程找到oep特别有成就感,虽然现在看来这样模仿似乎没什么用啦,大家都知道入门最难的了,有一段时间快坚持不下去了,非常感觉论坛的小糊涂虫大佬录了一段脱壳视频给我,让我继续学下去了。后来慢慢的又跟着网上的各种破解教程,攻防世界的CTF解题思路学习,然后思路似乎又偏了,想当黑客,学了一段时间web安全,最后又跟着论坛学了点安卓逆向知识。反正就是啥都学了啥都不会,哈哈。用ida 64位打开exe,所有工具吾爱破解的爱盘都有。

4.ida反编译的程序流程图很简单,c语言逻辑就是清晰明了,主要还是有字符串提示,不需要汇编知识也能看明白,现在有了ai,其实很多时候一段代码丢给ai就知道什么意思了,ida的f5功能挺好用,按下f5后就得到了伪代码。

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4[32]; // [rsp+20h] [rbp-20h] BYREF

  _main();
  printf("Please input password: ");
  scanf("%31s", v4);
  if ( (unsigned int)check_password(v4) )
    puts("Success! You cracked this reverseme.");
  else
    puts("Wrong password!");
  return 0;
}

5.有c语言基础的看这个就很清晰了,check_password函数返回值决定成功or失败,v4就是我们输入的字符串,双击就能进去了,进去看到const char a1常量指针其实就是v4那个字符串数组了,一个是实参,一个是形参而已,strcpy复制字符串hello123到v3,先判断长度是否相等,老实说a1[v3[3]] != ((_BYTE *)v3 + v3[3])这个看不懂。

__int64 __fastcall check_password(const char *a1)
{
  size_t v1; // rbx
  _DWORD v3[8]; // [rsp+20h] [rbp-60h] BYREF

  strcpy((char *)v3, "hello123");
  v1 = strlen(a1);
  if ( v1 != strlen((const char *)v3) )
    return 0i64;
  for ( v3[3] = 0; a1[v3[3]]; ++v3[3] )
  {
    if ( a1[v3[3]] != *((_BYTE *)v3 + v3[3]) )
      return 0i64;
  }
  return 1i64;
}

6.这一段看不懂,就去看for循环,第一个肯定就是int i=0,第三个基本就是i++,v3[3] = 0,是不是很像?直接替换v3[3]为i,数组和指针本质一样,下标加一和指针加一,如果内存区域存放同样的数据是等价的,这里做了一个强制转换保证都是1字节。

  • *a1[i] 等价 `(_BYTE )v3 + i`**
  • 指针是什么类型,+1 就跳几个字节
    • char* / _BYTE* → +1 偏移 1 字节
    • int* / _DWORD* → +1 偏移 4 字节
    • long long* / _QWORD* → +1 偏移 8 字节
  for ( i = 0; a1[i]; ++i )
  {
    if ( a1[i] != *((_BYTE *)v3 + i) )
      return 0i64;
  }
  return 1i64;
}

7.现在好理解了,就是比较每一个字符是否相等,异或似乎被编译优化掉了,小学数学运算大家都知道,同加一个数,同乘一个数,两边相等,这里同时异或一个数,所以去掉异或也是等价的,其实看到这里密码就知道了,hello123没经过任何变化,密码就是hello123,输入验证成功,这就是加解密的魅力,也是吸引我的地方。

8.使用x64dbg调试器加载程序,其实我更多的是用吾爱32位od,64位程序我都不敢碰,感觉很复杂,让豆包整理一下常用功能。

快捷键 功能 简要说明
F7 单步步入 StepInto 遇到 call 进入函数内部(比如进入 check_password)
F8 单步步过 StepOver 遇到 call 不进函数,直接执行完这个 call
F4 运行到光标处 Run to selection 光标放在目标行,直接运行到此停下,无需手动下断点
F2 切换软件断点 当前行 添加 / 取消断点
Ctrl+G 跳转到地址 / 表达式 输入内存地址,直接跳转
-(主键盘减号) 视图后退 双击 call 进去浏览代码后,回上一处浏览位置(不回程序执行流
+(主键盘加号) 视图前进 后退之后,再前进

9.搜索当前模板,字符串,通过字符串定位过来,就能看到输入提示语,输出提示语,call 项目1.401530这里面只有这一个函数未识别,可能就是check_password函数,打上断点。

00000000004015D7 | 48:8D0D 222A0000         | lea rcx,qword ptr ds:[404000]           | 0000000000404000:"Please input password: "
00000000004015DE | E8 E5150000              | call <JMP.&printf>                      |
00000000004015E3 | 48:8D45 E0               | lea rax,qword ptr ss:[rbp-20]           |
00000000004015E7 | 48:89C2                  | mov rdx,rax                             |
00000000004015EA | 48:8D0D 272A0000         | lea rcx,qword ptr ds:[404018]           | 0000000000404018:"%31s"
00000000004015F1 | E8 DA150000              | call <JMP.&scanf>                       |
00000000004015F6 | 48:8D45 E0               | lea rax,qword ptr ss:[rbp-20]           |
00000000004015FA | 48:89C1                  | mov rcx,rax                             |
00000000004015FD | E8 2EFFFFFF              | call 项目1.401530                         |
0000000000401602 | 85C0                     | test eax,eax                            |
0000000000401604 | 0F95C0                   | setne al                                |
0000000000401607 | 84C0                     | test al,al                              |
0000000000401609 | 74 0E                    | je 项目1.401619                           |
000000000040160B | 48:8D0D 0E2A0000         | lea rcx,qword ptr ds:[404020]           | 0000000000404020:"Success! You cracked this reverseme."
0000000000401612 | E8 C1150000              | call <JMP.&puts>                        |
0000000000401617 | EB 0C                    | jmp 项目1.401625                          |
0000000000401619 | 48:8D0D 252A0000         | lea rcx,qword ptr ds:[404045]           | 0000000000404045:"Wrong password!"
0000000000401620 | E8 B3150000              | call <JMP.&puts>                        |

10.这种代码简单的我还能看懂,套一点算法我就懵逼了,看不懂逻辑,ai看得懂逻辑,但不一定全对,经常错一点,找不出原因。运行,随便输入123123,F7进去函数,F8单步调试看看,只要有耐心,多来几遍,应该还是能猜到这里的大致功能。

0000000000401567 | E8 2C160000              | call <JMP.&strlen>                      |
000000000040156C | 48:39C3                  | cmp rbx,rax                             |
000000000040156F | 74 07                    | je 项目1.401578                           |
0000000000401571 | B8 00000000              | mov eax,0                               |
0000000000401576 | EB 4B                    | jmp 项目1.4015C3                          |

这里长度不相等,跳向失败,改一下右边ZF标志,让他跳转,然后就来到了for循环,逐字节比较是否相等,全部相等就返回1。

0000000000401581 | 8B45 AC                  | mov eax,dword ptr ss:[rbp-54]           |
0000000000401584 | 48:63D0                  | movsxd rdx,eax                          |
0000000000401587 | 48:8B45 D0               | mov rax,qword ptr ss:[rbp-30]           | [rbp-30]:"123123"
000000000040158B | 48:01D0                  | add rax,rdx                             |
000000000040158E | 0FB610                   | movzx edx,byte ptr ds:[rax]             |
0000000000401591 | 8B45 AC                  | mov eax,dword ptr ss:[rbp-54]           |
0000000000401594 | 48:98                    | cdqe                                    |
0000000000401596 | 0FB64405 A0              | movzx eax,byte ptr ss:[rbp+rax-60]      |
000000000040159B | 38C2                     | cmp dl,al                               |

二、豆包:用 c++ 语言写一个入门级 reserveme 给我

1.得到了如下的代码:

#include <iostream>

bool Verify(const char* in)
{
    // 原始密码 reverse123,每个字节异或0x05保存
    char secret[] = {0x73,0x62,0x62,0x68,0x69,0x65,0x34,0x37,0x36,0x00};
    int idx = 0;
    while (true)
    {
        char a = in[idx];
        char b = secret[idx] ^ 0x05;
        if (a != b)
            return false;
        if (a == '\0')
            return true;
        idx++;
    }
}

int main()
{
    char buf[128]{};
    std::cout << "Password: ";
    std::cin >> buf;
    std::cout << (Verify(buf) ? "Success\n" : "Fail\n");
    return 0;
}

2.编译运行一下,用ida打开看看,这代码函数名就长了,当然了由于都是最基本的判断、输出代码,所以整个程序看上去也不复杂,F5看一下伪代码

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char *v3; // rax
  char v5[144]; // [rsp+20h] [rbp-60h] BYREF

  _main();
  memset(v5, 0, 0x80ui64);
  std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "Password: ");
  std::operator>><char,std::char_traits<char>>(refptr__ZSt3cin, v5);
  if ( (unsigned __int8)Verify(v5) )
    v3 = "Success\n";
  else
    v3 = "Fail\n";
  std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, v3);
  return 0;
}

3.一样的步骤,进去看看,相比c,这个数据类型又变化了,好在逻辑简单,去掉数据类型修饰符还是能看懂赋值语句,和前面一样重命名得到类似代码,这里sbbhie476拷贝给v2,但是HIBYTE(v2[2]看不懂,BYTE2(v2[2]看不懂,想想以前数学未知数设x和y,这里我也设置一下,看作整体可能好理解一点,这样我的脑子终于能理解了,x就是我们输入的字符串,取出sbbhie476每一个字符异或5,然后给y,最后判断x是否不等于y,是的话返回0代表失败,这样一看,加解密的魅力与数学基本知识结合的挺紧密的。

__int64 __fastcall Verify(const char *a1)
{
  _DWORD v2[4]; // [rsp+0h] [rbp-10h] BYREF

  strcpy((char *)v2, "sbbhie476");
  for ( v2[3] = 0; ; ++v2[3] )
  {
    HIBYTE(v2[2]) = a1[v2[3]];
    BYTE2(v2[2]) = *((_BYTE *)v2 + v2[3]) ^ 5;
    if ( HIBYTE(v2[2]) != BYTE2(v2[2]) )
      return 0i64;
    if ( !HIBYTE(v2[2]) )
      break;
  }
  return 1i64;
}

重命名后

__int64 __fastcall Verify(const char *a1)
{
  _DWORD v2[4]; // [rsp+0h] [rbp-10h] BYREF

  strcpy((char *)v2, "sbbhie476");
  for ( i = 0; ; ++i )
  {
    x = a1[i];
    y = *((_BYTE *)v2 + i) ^ 5;
    if ( x != y )
      return 0i64;
    if ( !x )
      break;
  }
  return 1i64;
}

4.以前我就在想,两个不知道的数,为什么可以设x和y呢?现在想一想设啥都行,主要是部分到整体的思维,而我们普通人的脑容量有限,理解不了长难句,但是短句还是一听就懂,探索加密解密,攻防领域使我挺快乐的。打开x64dbg看看吧,搜索当前模块字符串,跳转过来,看看程序流程图,按G键还挺好的,和ida看到的结构差不多,对了,ida是空格键切换汇编和程序流程图的。

5.似乎这里函数名都没识别,其实只看sub开头的就行了,其他的应该都是C++库函数了,C++的程序相当于套了一层外衣,好讨厌,一点也没有C语言看的那么顺,脑子烧穿了。401530这里下个断点,F2,F7,F8走吧,看cmp,al是我输入的1,rbp-6是v,不相等,改zf吧,算了,直接改jmp吧,第二次循环,2是我输入的,g是异或5之后的。

000000000040156B | 8B45 FC                  | mov eax,dword ptr ss:[rbp-4]            |
000000000040156E | 48:63D0                  | movsxd rdx,eax                          |
0000000000401571 | 48:8B45 10               | mov rax,qword ptr ss:[rbp+10]           | [rbp+10]:"123321"
0000000000401575 | 48:01D0                  | add rax,rdx                             |
0000000000401578 | 0FB600                   | movzx eax,byte ptr ds:[rax]             |
000000000040157B | 8845 FB                  | mov byte ptr ss:[rbp-5],al              |
000000000040157E | 8B45 FC                  | mov eax,dword ptr ss:[rbp-4]            |
0000000000401581 | 48:98                    | cdqe                                    |
0000000000401583 | 0FB64405 F0              | movzx eax,byte ptr ss:[rbp+rax-10]      |
0000000000401588 | 83F0 05                  | xor eax,5                               |
000000000040158B | 8845 FA                  | mov byte ptr ss:[rbp-6],al              |
000000000040158E | 0FB645 FB                | movzx eax,byte ptr ss:[rbp-5]           |
0000000000401592 | 3A45 FA                  | cmp al,byte ptr ss:[rbp-6]              |
0000000000401595 | 74 07                    | je 项目1.40159E                           |
0000000000401597 | B8 00000000              | mov eax,0                               |
000000000040159C | EB 13                    | jmp 项目1.4015B1                          |
000000000040159E | 807D FB 00               | cmp byte ptr ss:[rbp-5],0               |
00000000004015A2 | 75 07                    | jne 项目1.4015AB                          |
00000000004015A4 | B8 01000000              | mov eax,1                               |
00000000004015A9 | EB 06                    | jmp 项目1.4015B1                          |
00000000004015AB | 8345 FC 01               | add dword ptr ss:[rbp-4],1              |
00000000004015AF | EB BA                    | jmp 项目1.40156B                          |

6.实在是讨厌这种一个字节字节比较,不会在内存中暴漏完整解密字符串,长度不够退出了,重来,输入的字符串改成reverse123试试,这个是豆包给我生成代码时提示的正确密码,0000000000401595这一行按空格,je改jmp强制跳吧,在上面cmp处打上断点,记录每次解密的值,似乎ai给我的密码不对啊,我去看下程序,靠代码字节才9位,你是怎么敢在注释上和我说密码是reverse123的,位数都不对啊,算了,我自己拼接吧:vggml`123。

  • r v
  • e g
  • v g
  • e m
  • r l
  • s '
  • e 1
  • 1 2
  • 2 3
  • 3 ?

7.你以为ai就给你挖这个坑,你输入这个vggml`123还是fail,为什么?回去看看给的源代码,先异或了0x5,这还怎么进入return true的那个if,这个判断你不放前面放后面???哪怕结束0了,异或一下又进循环了,那我密码永远不对。

 while (true)
    {
        char a = in[idx];
        char b = secret[idx] ^ 0x05;
        if (a != b)
            return false;
        if (a == '\0')
            return true;
        idx++;
    }

8.关键是我问了几次ai,都给我说这段代码是对的,还给我分析的头头是道,看起来有理有据,我以为的ai是自动渗透、自动逆向,这普通网页版ai办不到啊,可能还得是氪金大佬用的ai准确性高吧,不过只是把c代码换成c++代码,难度似乎倍增了。

三、豆包:用 Js 语言写一个入门级 reserveme 给我

1.得到了如下代码:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>JS ReverseMe</title>
</head>
<body>
<script>
// 混淆数组
const _0x2f9b = ['charCodeAt', 'fromCharCode', 'prompt', 'alert'];
const _0x7c1e = function(_0x1a3c, _0x5d4b) {
    return _0x2f9b[_0x1a3c];
};

// 核心校验函数(加密逻辑:原始字节 ^ 5)
function checkFlag(_0xinput) {
    // 密钥原始串:sbbhie476
    const secretRaw = [0x73,0x62,0x62,0x68,0x69,0x65,0x34,0x37,0x36];
    for (let i = 0; i < secretRaw.length; i++) {
        const inCode = _0xinput[_0x7c1e(0)](i);
        const realCode = secretRaw[i] ^ 5;
        if (inCode !== realCode) {
            return false;
        }
    }
    return true;
}

const userInput = window[_0x7c1e(2)]("请输入flag:");
if (checkFlag(userInput)) {
    window[_0x7c1e(3)]("✅ Correct! You solved JS Reverseme");
} else {
    window[_0x7c1e(3)]("❌ Wrong flag");
}
</script>
</body>
</html>

2.运行一下看看效果,输入错误提示❌ Wrong flag,看到弹窗,其实就知道window[_0x7c1e(3)]肯定就是alert函数了。

3.查看代码,js怎么查看源代码就不用说怎么操作了,F12就行了,整个代码checkFlag函数里面_0xinput_0x7c1e(0)就这里有混淆了,逐个向上搜索发现其实就是charCodeAt函数

const _0x7c1e = function(_0x1a3c, _0x5d4b)    //_0x1a3c = 0

 _0x2f9b[_0x1a3c] =charCodeAt

4.可以看出这个就是取出字符对应的ASCII码,然后和我输入字符的ASCII比较,在比较前先做了异或了5。同样这里也是按位比较,有一位不同就返回false。同样试试断点功能,不过这里可以直接用控制台打印变量,例如打印realCode。

console.log(realCode);
VM245:1 118

5.因为代码逻辑已经读懂,那么我就可以直接在控制台运行解密脚本,将realCode值每一个值异或5输出。

const secretRaw = [0x73,0x62,0x62,0x68,0x69,0x65,0x34,0x37,0x36];
let flag = "";
for(let i=0;i<secretRaw.length;i++){
    flag += String.fromCharCode(secretRaw[i]^5);
}
console.log(flag);

VM286:6 vggml`123

6.vggml`123输入进去,验证一下,成功。

四、日记

1.正经人谁写日记,只有像小菜鸟这样不务正业的才会有空乱写一篇文章,说实话,学的时间很久了,想了一下自己其实入门都没有,加解密也许自带魅力,让人欲罢不能,这么多年虽然没进步,但还是发了不少文章。

2.最近没找到工作,进机械厂了,没有手艺,没有技术,再加上武汉这就业市场,工作不好找,只能有啥干啥了,一个月多加点班,到手5000+没问题,属于饿不死自己的那种。

3.这几天感冒了,请假三天回来躺着了,人一闲下来就容易胡思乱想了,为了防止自己抑郁,原想再录点啥视频,仔细想想,自己讲的还没有ai说的全,最后就变成了算是一份日记吧。

4.免费的网页版ai在写代码,分析程序的时候,太容易产生幻觉了,给你一堆看似正确的逻辑却是错误的答案,因为网页版ai执行不了我们的代码,本质还是靠猜想,准确率上不去。

免费评分

参与人数 6吾爱币 +5 热心值 +4 收起 理由
Tyler9 + 1 我很赞同!
谁人定我去或留 + 1 + 1 加油
zxinyun + 1 必须给个赞!
skyisblue + 1 谢谢@Thanks!
IcePlume + 1 + 1 热心回复!
林尼玛 + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
涛之雨 发表于 2026-8-31 10:16
AI只是个工具,就好像电脑也只是个工具一样,没有必要焦虑

另外可以尝试用MCP(ida,xdbg之类的)直接让AI自己分析,

还有就是AI重构,虽然改的乱七八糟的,拆的七零八落的,目标也算是完成了七七八八,调整了七八遍(其实不止)跑的时候还是会有问题。但是终归是个工具:这个工具智能还算智能,就是不太可靠

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
小菜鸟一枚 + 1 + 1 我很赞同!

查看全部评分

推荐
shm382 发表于 2026-8-30 08:45
祝楼主早日康复!人生一世,草木一秋,没有什么大不了的,终究虚空一场,把心态放好,健康开心就好,其它都是浮云。
3#
gfy82 发表于 2026-8-30 09:20
4#
放羊的狼 发表于 2026-8-30 10:21
大概看了一下楼主的帖子,存在着大量的焦虑和忧愁,曾经也差不多,适当取舍,祝好。

免费评分

参与人数 1热心值 +1 收起 理由
小菜鸟一枚 + 1 热心回复!

查看全部评分

5#
ParaIIeI 发表于 2026-8-30 10:29
写了好多啊,用心了
6#
zjfandy 发表于 2026-8-30 10:39
支持一下,非常赞
7#
wise123 发表于 2026-8-30 10:45
ai辅助,人为验证
8#
homehome 发表于 2026-8-30 10:55
生病了,去研究养生。养身体来想破解,耗精神。
病好精神足研究破解没问题。
9#
桀兄3712 发表于 2026-8-30 11:41
不行,我看不懂,你就是大佬。
10#
Mochen427 发表于 2026-8-30 14:22
ai时代下学习的一种方法,感谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-9-1 01:16

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表