<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[凌乱的杂货铺]]></title><description><![CDATA[哈喽~欢迎光临]]></description><link>https://blog.acg.ng</link><image><url>https://blog.acg.nghttps://i.postimg.cc/d08bz8NV/Snipaste-2024-08-20-22-18-43.webp</url><title>凌乱的杂货铺</title><link>https://blog.acg.ng</link></image><generator>Shiro (https://github.com/Innei/Shiro)</generator><lastBuildDate>Mon, 20 Apr 2026 11:37:06 GMT</lastBuildDate><atom:link href="https://blog.acg.ng/feed" rel="self" type="application/rss+xml"/><pubDate>Mon, 20 Apr 2026 11:37:06 GMT</pubDate><language><![CDATA[zh-CN]]></language><item><title><![CDATA[密码保存方案]]></title><description><![CDATA[<link rel="preload" as="image" href="https://pic.imgdb.cn/item/67346db5d29ded1a8c6e126e.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/67346dd0d29ded1a8c6e2f8c.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/67346de1d29ded1a8c6e4316.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/67346df3d29ded1a8c6e5809.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/67346e02d29ded1a8c6e6348.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/67346e12d29ded1a8c6e720e.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/67346e1dd29ded1a8c6e7b22.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/67346e28d29ded1a8c6e850e.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/67346e34d29ded1a8c6e8ff0.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/67346e43d29ded1a8c6ea4b0.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/67346e4fd29ded1a8c6eb19c.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/67346e5dd29ded1a8c6ec3b7.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/67346e68d29ded1a8c6ecfc4.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/67346e79d29ded1a8c6ee095.png"/><div><blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href="https://blog.acg.ng/posts/sec/20241113MM">https://blog.acg.ng/posts/sec/20241113MM</a></blockquote><div><h1 id="">环境背景</h1><p>基于上一篇博文简单讲述浏览器存储密码的问题，目前市面上主要存有以下几种解决方案</p><ol start="1"><li>将密码记录在密码本（物理），每次使用需翻开查阅</li><li>借助第三类密码管理软件</li><li>桌面、个人文件夹中使用txt或word等文档保存</li></ol><p>首先排除密码本，这种需要随身携带，给人一种退回“农耕时代”的感觉； 保存在文档中的方式，由于存在个性化差异，感觉稍好一点，但明文保存总感觉差点意思；于是把目光放在密码管理软件中，目前主流的密码管理软件有这几种：Bitwarden（支持自部署），lastpass（付费），Vaultwarden（支持自部署），1password（付费），keepassxc（本地），这几款都具有较高的可用性，笔者最终选定了keepassxc</p><h1 id="">软件安装</h1><p>官网链接：<a href="https://keepassxc.org/download/#code">https://keepassxc.org/download/#code</a></p><p>进入官网，选择适合自己的版本正常安装</p><p><img src="https://pic.imgdb.cn/item/67346db5d29ded1a8c6e126e.png"/></p><p>安装好后，这里我们根据需要创建账号密码数据库来存储账号数据，这里提供了从零开始创建空白数据库与导入自己的账号密码文件两种创建方式</p><p><img src="https://pic.imgdb.cn/item/67346dd0d29ded1a8c6e2f8c.png"/></p><p>按照提示输入创建数据库的名称后，需要设置解密时间，这里解密时间越长，安全性越高，相对应的，解密时间也会越长</p><p><img src="https://pic.imgdb.cn/item/67346de1d29ded1a8c6e4316.png"/></p><p>后边的高级设置中可对加密函数等进行设置</p><p><img src="https://pic.imgdb.cn/item/67346df3d29ded1a8c6e5809.png"/></p><p>继续下一步，会提示你输入数据库的密码，这里注意今后存储在该软件中的一切账号数据都会使用这个密码来加/解密，如后期遗失相当于丢失所有账号密码数据，因此，这个密码要具备如下特性：</p><ol start="1"><li>足够复杂</li><li>保证不会被遗忘</li></ol><p>为提高数据库破解难度，下方在密码之外可以添加密钥文件(可以是任何文件)，只有同时知道密码和密钥文件的前提下才能够访问软件中存储的账号数据，因此密钥文件最好选取内容不会发生变化的文件（如图片、音乐、pdf等）</p><p><img src="https://pic.imgdb.cn/item/67346e02d29ded1a8c6e6348.png"/></p><p>设置完成后就正式进入了软件界面，可以点击这个按钮添加账号密码信息，或在“数据库”中选择“导入”按钮，导入自己的账号信息数据</p><p><strong>注意</strong>： 数据库建好后可随意移动，要打开现有数据库，请执行以下步骤：</p><ol start="1"><li>打开您的KeePassXC应用程序。单击“打开现有数据库”按钮或从“最近数据库”列表中选择一个最近数据库。</li><li>输入数据库的密码。</li><li>（可选）如果在创建数据库时选择了密钥文件作为其他身份验证因素，则浏览该密钥文件。</li><li>单击确定</li></ol><h1 id="">浏览器插件</h1><p>试想，每次输入账号密码的时候，都需要打开KeePassXC查找到自己要找的账号，然后把账号和密码都复制到浏览器中，这个过程太麻烦繁琐，我们理想中应该是软件能够自动完成账号和密码的填充，好在KeePassXC提供了相应的浏览器插件支持，能够完成上述操作</p><p>链接：<a href="https://keepassxc.org/download/#browser">https://keepassxc.org/download/#browser</a></p><p><img src="https://pic.imgdb.cn/item/67346e12d29ded1a8c6e720e.png"/></p><p><img src="https://pic.imgdb.cn/item/67346e1dd29ded1a8c6e7b22.png"/></p><p>首先按照提示安装好插件，然后在KeePassXC的设置界面，打开浏览器集成，并按照自身浏览器选择相应的集成环境</p><p><img src="https://pic.imgdb.cn/item/67346e28d29ded1a8c6e850e.png"/><img src="https://pic.imgdb.cn/item/67346e34d29ded1a8c6e8ff0.png"/></p><p>确保KeePassXC开启的情况下，点击浏览器插件，插件会自动检测连接状态，弹出“KeePassXC-Browser尚未设置”后，点击连接按钮，此时KeePassXC中会弹出关联请求，随意输入ID并保存后，就能够借助这一插件进行互联网密码的保存和自动输入</p><h1 id="">多端同步</h1><p>可能有人要说了，数据库只在本地，我有多台电脑，还有手机、平板，在一个设备中新增了账号密码，需要手动把数据库文件往每个设备都拷贝一份太麻烦，因此，需要借助三方服务来同步数据库</p><p>我这里采用的是坚果云同步(<a href="https://www.jianguoyun.com/">https://www.jianguoyun.com/</a>)，坚果云提供免费用户一个月1G的上传流量服务，对于几百K的数据库来说绰绰有余</p><p><img src="https://pic.imgdb.cn/item/67346e43d29ded1a8c6ea4b0.png"/></p><p>首先将数据库文件上传到坚果云(文件夹名字要求全是数字/字母)</p><p><img src="https://pic.imgdb.cn/item/67346e4fd29ded1a8c6eb19c.png"/></p><p>然后在右上角“账户”-&gt;“账户信息”-&gt;“安全选项”中，添加一个应用并生成密码</p><p>比如我的情况是在8123文件夹下边的8123.kdbx，因此，我的数据库信息如下：</p><blockquote><p>数据库Dav链接：<a href="https://dav.jianguoyun.com/dav/8123/8123.kdbx">https://dav.jianguoyun.com/dav/8123/8123.kdbx</a></p><p>账户：坚果云账户</p><p>密码：生成的应用密码</p></blockquote>
<p>电脑端通过安装坚果云进行同步，安卓端通过生成的数据库链接、账户和密码访问</p><h1 id="">应用填充</h1><p><img src="https://pic.imgdb.cn/item/67346e5dd29ded1a8c6ec3b7.png"/></p><p>首先应该选中需要自动填充的账号信息条目，右键选择编辑条目</p><p><img src="https://pic.imgdb.cn/item/67346e68d29ded1a8c6ecfc4.png"/></p><p>打开自动输入，在窗口关联中添加需要自动输入密码的窗口标题名，直接写“*”则表示在所有窗口都可以。</p><p><img src="https://pic.imgdb.cn/item/67346e79d29ded1a8c6ee095.png"/></p><p>更多的操作可以参考“入门指南”和“用户手册”</p><h1 id="">手机填充</h1><p>安卓端在应用市场下载Keepass2Android，采用上边生成的坚果云的WebDav地址、账号、密码即可</p></div><p style="text-align:right"><a href="https://blog.acg.ng/posts/sec/20241113MM#comments">看完了？说点什么呢</a></p></div>]]></description><link>https://blog.acg.ng/posts/sec/20241113MM</link><guid isPermaLink="true">https://blog.acg.ng/posts/sec/20241113MM</guid><dc:creator><![CDATA[master]]></dc:creator><pubDate>Wed, 13 Nov 2024 09:29:13 GMT</pubDate></item><item><title><![CDATA[2024KCTF-第二题 星际生物]]></title><description><![CDATA[<link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f822cff21886ccc0a6d334.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f82306f21886ccc0a70bf1.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f82324f21886ccc0a72e3e.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f82324f21886ccc0a72e56.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f82324f21886ccc0a72e77.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f82324f21886ccc0a72e89.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f82354f21886ccc0a7611f.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f82354f21886ccc0a76157.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f82354f21886ccc0a76173.jpg"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f82354f21886ccc0a76189.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f82383f21886ccc0a79368.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f82383f21886ccc0a79374.png"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f82383f21886ccc0a7937c.jpg"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f82383f21886ccc0a79347.jpg"/><div><blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href="https://blog.acg.ng/posts/ctf/20240904SJ">https://blog.acg.ng/posts/ctf/20240904SJ</a></blockquote><div><p>题目链接：<a href="https://ctf.kanxue.com/game-season_fight-243.htm">https://ctf.kanxue.com/game-season_fight-243.htm</a></p><p>首先解压，看到是个exe，查壳</p><p><img src="https://pic.imgdb.cn/item/66f822cff21886ccc0a6d334.png" alt="查壳"/></p><p>嗯，良民，无壳，用.NET写的，来人啊，拖进dnSpy</p><p><img src="https://pic.imgdb.cn/item/66f82306f21886ccc0a70bf1.png" alt="image-20240904203633518"/></p><p>无加密无混肴，很容易就找到了主函数，</p><p><img src="https://pic.imgdb.cn/item/66f82324f21886ccc0a72e3e.png" alt="image-20240904203724916"/></p><p>可以看到先对输入进行长度校验，不是70字节直接退出</p><p><img src="https://pic.imgdb.cn/item/66f82324f21886ccc0a72e56.png" alt="image-20240904203802618"/></p><p>然后又对前五位后一位进行校验，因此得出key应该是这样的形式：flag{*}</p><p><img src="https://pic.imgdb.cn/item/66f82324f21886ccc0a72e77.png" alt="image-20240904204030018"/></p><p>对剩余的64位key进行判断，如果不是0-9直接退出，并对内存中9*9的区域进行判断，如果区域数值不是0xF则跳过，否则从前到后写一位key的数值减去48后填进去（并且能看到前边有shuduku的字样）</p><p><img src="https://pic.imgdb.cn/item/66f82324f21886ccc0a72e89.png" alt="Snipaste_2024-09-04_20-46-12"/></p><p>这块9*9的区域中存放着什么数据？可以从文件偏移0x10800中找到，可以看到81个数字中有25位不是0xF，因此这边以此将64位key的前56位以此写入0xF的位置</p><p><img src="https://pic.imgdb.cn/item/66f82354f21886ccc0a7611f.png" alt="image-20240904205336003"/></p><p>这里对9*9区域的每一行进行校验，确保每一行数据没有重复，后边继续对每一列进行校验，确保没有重复，如有重复则程序退出，从这里就能看出这块9*9的区域为什么叫shudu了</p><p><img src="https://pic.imgdb.cn/item/66f82354f21886ccc0a76157.png" alt="image-20240904205818047"/></p><p>所以，想要拿到key就硬着头皮玩这个数独游戏吧~不过，我这里用python写了一个脚本</p><pre class="language-python lang-python"><code class="language-python lang-python">def is_valid(board, row, col, num):
    &quot;&quot;&quot;检查在数独板的某个位置放置数字num是否合法&quot;&quot;&quot;
    # 检查该行
    for i in range(9):
        if board[row][i] == num:
            return False
    
    # 检查该列
    for i in range(9):
        if board[i][col] == num:
            return False
    
    # 检查3x3的小方格
    start_row, start_col = 3 * (row // 3), 3 * (col // 3)
    for i in range(3):
        for j in range(3):
            if board[i + start_row][j + start_col] == num:
                return False
    return True

def solve_sudoku(board):
    &quot;&quot;&quot;使用回溯算法解决数独问题&quot;&quot;&quot;
    for row in range(9):
        for col in range(9):
            if board[row][col] == 0:
                for num in range(1, 10):
                    if is_valid(board, row, col, num):
                        board[row][col] = num
                        if solve_sudoku(board):
                            return True
                        board[row][col] = 0
                return False
    return True

def print_sudoku(board):
    &quot;&quot;&quot;格式化打印数独板&quot;&quot;&quot;
    for row in board:
        print(&quot; &quot;.join(str(num) if num != 0 else &quot;0F&quot; for num in row))

# 初始数独问题，0F表示空格
sudoku_board = [
    [0, 0, 2, 0, 0, 7, 0, 0, 0],
    [0, 6, 0, 9, 0, 0, 4, 0, 0],
    [0, 9, 0, 2, 5, 0, 0, 0, 3],
    [0, 0, 0, 4, 0, 0, 1, 0, 0],
    [7, 3, 0, 0, 6, 0, 0, 0, 0],
    [0, 0, 9, 5, 3, 0, 0, 6, 0],
    [0, 0, 6, 3, 4, 0, 0, 7, 0],
    [8, 0, 0, 0, 0, 0, 0, 0, 9],
    [0, 0, 0, 0, 0, 0, 0, 5, 0]
]

# 解决数独并打印解
if solve_sudoku(sudoku_board):
    print(&quot;Sudoku solved successfully:&quot;)
    print_sudoku(sudoku_board)
else:
    print(&quot;No solution exists.&quot;)</code></pre><p><img src="https://pic.imgdb.cn/item/66f82354f21886ccc0a76173.jpg" alt="Snipaste_2024-09-03_01-32-53"/></p><p>因此前边56位为34689155813271746868579324125982187492581517263447389126，继续往后看</p><p><img src="https://pic.imgdb.cn/item/66f82354f21886ccc0a76189.png" alt="image-20240904210512589"/></p><p>4*4区域赋值</p><p><img src="https://pic.imgdb.cn/item/66f82383f21886ccc0a79368.png" alt="image-20240904210548106"/></p><p>可以看到将key最后8位一一进行校验，初始坐标为（0，0），如果key为‘A’，则横坐标减一；为‘D’，则横坐标加一，‘W’和‘S’同理；并且横坐标不能大于3小于0，纵坐标不能大于3小于0，坐标对应的数值不能等于0x45</p><p><img src="https://pic.imgdb.cn/item/66f82383f21886ccc0a79374.png" alt="2"/></p><p>因此可以看出是一个走迷宫的小游戏，要求8步内从起点(33)走到终点(63)，因此后8位为SDSDDWWA</p><p>将key拼接起来就是flag{34689155813271746868579324125982187492581517263447389126SDSDDWWA}</p><p><img src="https://pic.imgdb.cn/item/66f82383f21886ccc0a7937c.jpg" alt="4"/></p><p>不过说起数独游戏...不知道有哪位大佬有兴趣尝试一下这个？</p><p><img src="https://pic.imgdb.cn/item/66f82383f21886ccc0a79347.jpg" alt="Snipaste_2024-09-03_01-31-13"/></p></div><p style="text-align:right"><a href="https://blog.acg.ng/posts/ctf/20240904SJ#comments">看完了？说点什么呢</a></p></div>]]></description><link>https://blog.acg.ng/posts/ctf/20240904SJ</link><guid isPermaLink="true">https://blog.acg.ng/posts/ctf/20240904SJ</guid><dc:creator><![CDATA[master]]></dc:creator><pubDate>Sat, 28 Sep 2024 15:47:26 GMT</pubDate></item><item><title><![CDATA[2024KCTF-第七题 星际移民]]></title><description><![CDATA[<link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f82774f21886ccc0ab90c5.webp"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f82774f21886ccc0ab90de.webp"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f82774f21886ccc0ab90b8.webp"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f827bcf21886ccc0abdc8c.webp"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f827bcf21886ccc0abdcbd.webp"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f827bcf21886ccc0abdce2.webp"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f827bcf21886ccc0abdd04.webp"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f827bcf21886ccc0abdc71.webp"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f82804f21886ccc0ac226a.webp"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f82804f21886ccc0ac21f3.webp"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f82804f21886ccc0ac221f.webp"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66f82804f21886ccc0ac224c.webp"/><div><blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href="https://blog.acg.ng/posts/ctf/20240928_2024KCTF">https://blog.acg.ng/posts/ctf/20240928_2024KCTF</a></blockquote><div><font style="color:rgb(79, 79, 79)">题目类型 Reverse</font><p>题目链接：<a href="https://ctf.kanxue.com/game-season_fight-250.htm">https://ctf.kanxue.com/game-season_fight-250.htm</a></p><p>首先查壳，无壳，ida走起</p><pre class="language-plain lang-plain"><code class="language-plain lang-plain">; int __cdecl main(int argc, const char **argv, const char **envp)
_main proc near

argc= dword ptr  4
argv= dword ptr  8
envp= dword ptr  0Ch

push    offset aInputUser ; &quot;Input User:\n&quot;
call    dword_403FDC
push    offset byte_403800
call    dword_403FD8
push    offset aInputSerial ; &quot;Input Serial:\n&quot;
call    dword_403FDC
push    offset byte_403418
call    dword_403FD8
push    offset off_403FD0
call    off_403FD4 ;校验
add     esp, 14h
call    ds:getchar
xor     eax, eax
retn
_main endp</code></pre><p>很明显能找到主函数，并且代码非常简单，提示用户输入用户名和密码后调用函数对密码进行校验后退出，很明显程序的主要功能都在17行的调用中实现，跟进去后很快就发现程序调用了sub_401000，根据题目中给的账号和密码，把程序拖进OD一顿分析，发现函数作用是将长度为0x86的密码从字符转换为长度0x45的十六进制(结尾两个0x00)，转换后的数据称为Serial_2，实例代码如下：</p><pre class="language-python lang-python"><code class="language-python lang-python">import binascii
binascii.a2b_hex(hex_input)
# 逆运算
binascii.b2a_hex(b_input)</code></pre><p><img src="https://pic.imgdb.cn/item/66f82774f21886ccc0ab90c5.webp"/></p><p>可以看到后边紧接着用自身程序0x401120开始的0x2B9字节与Serial_2进行异或，因此现在需要提取这0x2B9字节的数据</p><p><img src="https://pic.imgdb.cn/item/66f82774f21886ccc0ab90de.webp"/></p><p>通过查看目标程序，能够看到代码区.text的虚拟地址偏移为0x1000，大小为0xC00，加上Imagebase0x400000，得出代码区.text在程序进程中的内存地址范围为0x401000到0x401C00，自身程序0x401120开始的0x2B9字节落在了代码区段中。通过PointerToRawData和SizeOfRawData得知代码区.text在程序文件中的偏移地址为0x400到0x1000，因此从文件偏移0x400+0x120开始提取0x2B9字节。</p><pre class="language-python lang-python"><code class="language-python lang-python">code_401120 =binascii.a2b_hex( &quot;83EC4CA10030400033C48944244853555657BB18344000E8C4FEFFFF8BF0B9100000008D7C2414F3A566A550A4FF15B02040008B7C24648B770483C40433C990B86B4CA407F7E1D1EA6BD2438BC12BC28A1431305404148D4404144181F9B90200007CDC8A4C2414B8010000008D49008A5404143254041583C00532540411325404133254041232CA83F8427CE28A54245632D1885424568D442414B94200000030104083E90175F88A0D0038400033C0BA0038400084C9741A8D9B000000000FB6C933C881E1FF000000428BC18A0A84C975EC8B3783E00F8D4444148D542414894424102BC285C07E688BE88BFE83F80472148B0F3B0A751283ED0483C20483C70483FD0473EC85ED74470FB60F0FB61A2BCB753183FD0176380FB64F010FB65A012BCB752083FD0276270FB64F020FB65A022BCB750F83FD0376160FB64F030FB652032BCAC1F91F83C9010F85FF000000BF2C0000002BF885FF7E718D4C042B8D54301783FF047219EB038D49008B023B01751283EF0483C10483C20483FF0473EC85FF74470FB6020FB6312BC6753183FF0176380FB642010FB671012BC6752083FF0276270FB642020FB671022BC6750F83FF0376160FB642030FB649032BC1C1F81F83C8010F85830000008B7424108B542460B905000000BFE83B4000F3A566A5A48B7204BDE83B4000BF170000000FBE168A450083E207B1082ACA8AD8D2EB8BCAD2E046450AD883EF01885DFF75DF8D5717B8F8204000B9E83B40008B313B30752B83EA0483C00483C10483FA0473EC8A103A1175178A50013A5101750F8A40023A410275076830214000EB056840214000FF15A42040008B4C245C83C4045F5E5D5B33CCE80400000083C44CC33B0D003040007502F3C3E9AC020000688C184000E8A3040000A1B8524000C70424844F4000FF35B4524000A3844F400068744F400068784F400068704F4000FF159820400083&quot;)</code></pre><p><img src="https://pic.imgdb.cn/item/66f82774f21886ccc0ab90b8.webp"/></p><p>实例代码如下：</p><pre class="language-python lang-python"><code class="language-python lang-python">def mima_xor_hex(str1,str2):
    num_str1 = len(str1)
    num_str2 = len(str2)
    num = 0
    b_str1 = bytearray(str1)
    for i in range(num_str2):
        b_str1[num] ^= str2[i]
        print(&quot;%x&quot; %  b_str1[num])
        num+=1
        if num == num_str1:
            num = 0
    return b_str1

Serial_3 = mima_xor_hex(Serial_2,code_401120)
#逆运算还是该函数</code></pre><p><img src="https://pic.imgdb.cn/item/66f827bcf21886ccc0abdc8c.webp"/></p><p>继续往后看，这里通过调试可以看出是将Serial_3前0x42个字节进行xor，结果存在Serial_3[0x42]，然后用Serial_3[0x42]与Serial_3开始的0x42个字节分别进行xor，结果存在对应位置，得到Serial_4</p><p>实例代码如下：</p><pre class="language-python lang-python"><code class="language-python lang-python">def Serial_3to4(Serial_3):
    n = Serial_3[0]
    for i in range(0x42):
        n ^= Serial_3[i+1]
    Serial_3[0x42] = n
    for i in range(0x42):
        Serial_3[i] ^= n
    return Serial_3
#逆向
def Serial_4to3(Serial_4):
    n = Serial_4[0x42]
    for i in range(0x42):
        Serial_4[i] ^= n
    for i in range(0x42):
        n ^= Serial_3[i]
    Serial_3[0x42] = n
    return Serial_4</code></pre><p><img src="https://pic.imgdb.cn/item/66f827bcf21886ccc0abdcbd.webp"/></p><p>继续往后看，这里通过输入的用户名计算出一个数字data_1，示例代码如下：</p><pre class="language-python lang-python"><code class="language-python lang-python">def user_data(string_name):
    aaa = 0
    for i in name:
        aaa ^= ord(i)
    return (aaa &amp; 0xf)*2</code></pre><p>后边的代码看着比较乱，拖进ida瞅瞅</p><p><img src="https://pic.imgdb.cn/item/66f827bcf21886ccc0abdce2.webp"/></p><p>这里是一个简单的比较，比较Serial_4与0x4010D0开始的data_1个字节是否相同，相同则继续，不同则失败</p><p><img src="https://pic.imgdb.cn/item/66f827bcf21886ccc0abdd04.webp"/></p><p>Serial_4[data_1+0x17]与0x4010D0[data_1+0x17]开始比较0x2c-data_1个字节，相同则继续，不同则失败</p><p><img src="https://pic.imgdb.cn/item/66f827bcf21886ccc0abdc71.webp"/></p><p>首先取Serial_4[data_1]和0x401120[0]这两个字节，0x401120[0]&amp;0xf（只保留低3位，作为左位移位数），用0x8-0x401120[0]&amp;0xf得出右位移位数，对Serial_4[data_1]一次进行左位移和右位移，将左右位移结果进行或操作写在Serial_4[data_1]，得到Serial_5</p><p>按照上述步骤合计进行0x17此操作，此时数据区已经能够明显的看到Serial_5为一串明文</p><p><img src="https://pic.imgdb.cn/item/66f82804f21886ccc0ac226a.webp"/></p><p><img src="https://pic.imgdb.cn/item/66f82804f21886ccc0ac21f3.webp"/></p><p>最后果不其然对Serial_5进行判断，其值如果为“KCTF-2024-CRACK-SUCCESS”则判断成功，否则视为失败，至此，整个流程分析结束</p><hr/><p>不难看出密码被分为三段，分别为[0,data_1)，[data_1,0x17+data_1)，[0x17+data_1,0x2c+0x17)，这三段分别进行不同校验，而题目给定的用户名用来计算data_1，data_1确定之后对三块区域进行拼接+逆运算即可</p><p><img src="https://pic.imgdb.cn/item/66f82804f21886ccc0ac221f.webp"/></p><p><img src="https://pic.imgdb.cn/item/66f82804f21886ccc0ac224c.webp"/></p><p>破解机代码：</p><pre class="language-python lang-python"><code class="language-python lang-python">import binascii

def mima_xor_hex(str1,str2):
    num_str1 = len(str1)
    num_str2 = len(str2)
    num = 0
    if type(str1) != bytearray:
     b_str1 = bytearray(str1)
    else:
     b_str1 = str1
    for i in range(num_str2):
        b_str1[num] ^= str2[i]
        num+=1
        if num == num_str1:
            num = 0
    return b_str1

def Serial_3to4(Serial_3):
    n = Serial_3[0]
    for i in range(0x42):
        n ^= Serial_3[i+1]
    Serial_3[0x42] = n
    for i in range(0x42):
        Serial_3[i] ^= n
    return Serial_3

def Serial_4to3(Serial_4_):
    Serial_4 = bytearray(Serial_4_)
    n = Serial_4[0x42]
    for i in range(0x42):
        Serial_4[i] ^= n
    for i in range(0x42):
        n ^= Serial_4[i]
    Serial_4[0x42] = n
    return Serial_4

def user_data(string_name):
    aaa = 0
    for i in name:
        aaa ^= ord(i)
    return (aaa &amp; 0xf)*2

code_401120 =binascii.a2b_hex( &quot;83EC4CA10030400033C48944244853555657BB18344000E8C4FEFFFF8BF0B9100000008D7C2414F3A566A550A4FF15B02040008B7C24648B770483C40433C990B86B4CA407F7E1D1EA6BD2438BC12BC28A1431305404148D4404144181F9B90200007CDC8A4C2414B8010000008D49008A5404143254041583C00532540411325404133254041232CA83F8427CE28A54245632D1885424568D442414B94200000030104083E90175F88A0D0038400033C0BA0038400084C9741A8D9B000000000FB6C933C881E1FF000000428BC18A0A84C975EC8B3783E00F8D4444148D542414894424102BC285C07E688BE88BFE83F80472148B0F3B0A751283ED0483C20483C70483FD0473EC85ED74470FB60F0FB61A2BCB753183FD0176380FB64F010FB65A012BCB752083FD0276270FB64F020FB65A022BCB750F83FD0376160FB64F030FB652032BCAC1F91F83C9010F85FF000000BF2C0000002BF885FF7E718D4C042B8D54301783FF047219EB038D49008B023B01751283EF0483C10483C20483FF0473EC85FF74470FB6020FB6312BC6753183FF0176380FB642010FB671012BC6752083FF0276270FB642020FB671022BC6750F83FF0376160FB642030FB649032BC1C1F81F83C8010F85830000008B7424108B542460B905000000BFE83B4000F3A566A5A48B7204BDE83B4000BF170000000FBE168A450083E207B1082ACA8AD8D2EB8BCAD2E046450AD883EF01885DFF75DF8D5717B8F8204000B9E83B40008B313B30752B83EA0483C00483C10483FA0473EC8A103A1175178A50013A5101750F8A40023A410275076830214000EB056840214000FF15A42040008B4C245C83C4045F5E5D5B33CCE80400000083C44CC33B0D003040007502F3C3E9AC020000688C184000E8A3040000A1B8524000C70424844F4000FF35B4524000A3844F400068744F400068784F400068704F4000FF159820400083&quot;)
code_4010D0 = binascii.a2b_hex(&quot;6810214000FF15DC3F40006800384000FF15D83F40006820214000FF15DC3F40006818344000FF15D83F400068D03F4000FF15D43F400083C414FF15A020400033C0C3&quot;)

name = input(&quot;input your name:&quot;)
name_data = user_data(name)
Serial_4 = code_4010D0[0:name_data] + binascii.a2b_hex(&quot;693445232D32303286D2A125144369694DAA6843545353&quot;) + code_4010D0[name_data+0x17:0x43]
Serial_3 = Serial_4to3(Serial_4)
Serial_2 = mima_xor_hex(Serial_3,code_401120)
print(binascii.b2a_hex(Serial_2))</code></pre></div><p style="text-align:right"><a href="https://blog.acg.ng/posts/ctf/20240928_2024KCTF#comments">看完了？说点什么呢</a></p></div>]]></description><link>https://blog.acg.ng/posts/ctf/20240928_2024KCTF</link><guid isPermaLink="true">https://blog.acg.ng/posts/ctf/20240928_2024KCTF</guid><dc:creator><![CDATA[master]]></dc:creator><pubDate>Sat, 28 Sep 2024 15:31:22 GMT</pubDate></item><item><title><![CDATA[获取chrome浏览器保存的账户密码]]></title><description><![CDATA[<link rel="preload" as="image" href="https://pic.imgdb.cn/item/66ce1817d9c307b7e999bfa9.webp"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66ce1817d9c307b7e999bfaf.webp"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66ce1817d9c307b7e999bf6d.webp"/><link rel="preload" as="image" href="https://pic.imgdb.cn/item/66ce1817d9c307b7e999bf8c.webp"/><div><blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href="https://blog.acg.ng/posts/sec/20240828SJ_MM">https://blog.acg.ng/posts/sec/20240828SJ_MM</a></blockquote><div><h1 id="">故事背景</h1><p>上级部门要求严禁在浏览器中存储任何系统账户用户名和密码，因为这样存储不安全，<del class="spoiler" title="你知道的太多了">你讲得这些我都懂，但我偏偏就不做</del>，平时单位系统本来就多，除单位系统之外，还会有百度云、知乎、税务系统等网站也需要保存账号和密码，总不能再回到山顶洞人时期都记录在本子上吧，<del class="spoiler" title="你知道的太多了">所以又让大家不要保存密码，又不提供切实可行的解决方案</del>。</p><h1 id="">凭什么听它的？</h1><p>众所周知，存储在chrome、火狐、edge、360、qq等浏览器中的密码都不是那么的安全，就以我用的chrome浏览器为例：</p><p>首先在chrome浏览器中添加一个账户/密码，在chrome浏览器中可以从“右上角三个点-&gt;密码和自动填充-&gt;Google 密码管理工具”打开，然后输入windows系统登录密码就可以查看对应的账号和密码。</p><p><img src="https://pic.imgdb.cn/item/66ce1817d9c307b7e999bfa9.webp"/></p><p>此时，可以在如下链接中看到名为“Login Data”的文件，该文件就是记录着用户账户密码文件</p><blockquote><p>%LocalAppData%\Google\Chrome\User Data\Default\Login Data</p></blockquote>
<p>而这个文件其实是一个SQLite数据库文件：</p><p><img src="https://pic.imgdb.cn/item/66ce1817d9c307b7e999bfaf.webp"/></p><p>SQLite可在此链接下载：<a href="https://sqlitestudio.pl/">https://sqlitestudio.pl/</a></p><p>使用SQLite打开文件即可看到其中赫然记录着我们刚才添加的账户信息，不过看样子密码已经经过加密处理，无法直接看到原文，看起来好像并没有大家说的那么不堪？但故事往往并没有那么简单。
<img src="https://pic.imgdb.cn/item/66ce1817d9c307b7e999bf6d.webp"/></p><p>众所周知chrome浏览器的内核是chromium，而chromium是开源的，因此，有没有可能通过源码获取这里的加密手段？遂和google进行了一阵友好交流，在chromium源码中定位到一个关键文件os_crypt_win.cc</p><blockquote><p><a href="https://source.chromium.org/chromium/chromium/src/+/main:components/os_crypt/sync/os_crypt_win.cc">https://source.chromium.org/chromium/chromium/src/+/main:components/os_crypt/sync/os_crypt_win.cc</a></p></blockquote>
<p>在下边的代码中能看到有一个字符串加密函数</p><pre class="language-c++ lang-c++"><code class="language-c++ lang-c++">bool OSCryptImpl::EncryptString(const std::string&amp; plaintext,
                            std::string* ciphertext) {
  if (use_legacy_)
    //在windows系统中use_legacy_为false，即不使用下边老旧的加密方法
    return EncryptStringWithDPAPI(plaintext, ciphertext);
  //这里可以看到使用了AES256进行加密
  crypto::Aead aead(crypto::Aead::AES_256_GCM);
  //GetRawEncryptionKey函数获取密钥
  const auto key = GetRawEncryptionKey();
  aead.Init(&amp;key);

  //数据边界检查
  DCHECK_EQ(kKeyLength, aead.KeyLength());
  DCHECK_EQ(kNonceLength, aead.NonceLength());
  //初始化随机字符串
  std::string nonce(kNonceLength, &#x27;\0&#x27;);
  crypto::RandBytes(base::as_writable_byte_span(nonce));
  //进行加密处理
  if (!aead.Seal(plaintext, nonce, std::string(), ciphertext))
    return false;
  
  ciphertext-&gt;insert(0, nonce);
  //kEncryptionVersionPrefix值为&#x27;v10&#x27;，这与上边数据库中查看到加密数据的标志头一致
  ciphertext-&gt;insert(0, kEncryptionVersionPrefix);
  return true;
}</code></pre><p>AES是一种对称密钥加密算法，解密和加密密钥是相同的，因此，我们知道了加密算法后还应获取到对应的密钥才能对密码进行解密，通过翻阅代码发现，OSCryptImpl类在初始化的时候就已经生成密钥并进行存储</p><pre class="language-c++ lang-c++"><code class="language-c++ lang-c++">bool OSCryptImpl::Init(PrefService* local_state) {
  // 判断密钥状态
  switch (InitWithExistingKey(local_state)) {
    case OSCrypt::kSuccess:
      return true;
    case OSCrypt::kKeyDoesNotExist:
      break;
    case OSCrypt::kInvalidKeyFormat:
      return false;
    case OSCrypt::kDecryptionFailed:
      break;
  }
    
  // 在密钥不存在或解密密钥失败的情况下重新生成一个密钥
  std::string key(kKeyLength, &#x27;\0&#x27;);
  crypto::RandBytes(base::as_writable_byte_span(key));
  // 将密钥存储在本地
  if (!EncryptAndStoreKey(key, local_state)) {
    return false;
  }
    
  // 标志位
  local_state-&gt;SetBoolean(kOsCryptAuditEnabledPrefName, true);
  // 将生成的密钥分配给encryption_key_
  encryption_key_.assign(key);
  return true;
}</code></pre><p>通过参数名字+谷歌搜索确定密钥路径在如下路径的json文件中</p><blockquote><p>%LocalAppData%\Google\Chrome\User Data\Local State</p></blockquote>
<p>继续跟进存储函数</p><pre class="language-c++ lang-c++"><code class="language-c++ lang-c++">bool EncryptAndStoreKey(const std::string&amp; key, PrefService* local_state) {
  std::string encrypted_key;
  // 在EncryptStringWithDPAPI函数中对密钥进行CryptProtectData函数加密
  if (!EncryptStringWithDPAPI(key, &amp;encrypted_key)) {
    return false;
  }

  // kDPAPIKeyPrefix值为&#x27;DPAPI&#x27;
  encrypted_key.insert(0, kDPAPIKeyPrefix);
  // 可以看到将密钥进行base64编码
  std::string base64_key = base::Base64Encode(encrypted_key);
  // kOsCryptEncryptedKeyPrefName值为&quot;os_crypt.encrypted_key&quot;，此处可知道密钥存储在json文件的os_crypt.encrypted_key后边
  local_state-&gt;SetString(kOsCryptEncryptedKeyPrefName, base64_key);
  return true;
}</code></pre><h1 id="">梳理思路</h1><p>整个流程梳理是这样的，首先生成密钥A，通过A对用户密码进行AES256加密，并存放在名为“Login Data”的SOLite数据库中，然后对密钥A通过CryptProtectData函数加密，再经过base64编码放在“Local State”文件中的os_crypt.encrypted_key后边，因此，解密流程应该倒着来。</p><pre class="language-python lang-python"><code class="language-python lang-python">#获取密钥
def get_secret_key():
    try:
        with open( CHROME_PATH_LOCAL_STATE, &quot;r&quot;, encoding=&#x27;utf-8&#x27;) as f:
            local_state = f.read()
            local_state = json.loads(local_state)
        secret_key = base64.b64decode(local_state[&quot;os_crypt&quot;][&quot;encrypted_key&quot;])
        # 移去标志头
        secret_key = secret_key[5:]
        secret_key = win32crypt.CryptUnprotectData(secret_key, None, None, None, 0)[1]
        return secret_key
    except Exception as e:
        print(&quot;%s&quot;%str(e))
        return None
#AES解密
def decrypt_password(ciphertext, secret_key):
    try:
        initialisation_vector = ciphertext[3:15]
        encrypted_password = ciphertext[15:-16]
        cipher = generate_cipher(secret_key, initialisation_vector)
        decrypted_pass = decrypt_payload(cipher, encrypted_password)
        decrypted_pass = decrypted_pass.decode()  
        return decrypted_pass
    except Exception as e:
        print(&quot;%s&quot;%str(e))
        return None</code></pre><p>最终成功解密看到登录网址、账号和密码</p><p><img src="https://pic.imgdb.cn/item/66ce1817d9c307b7e999bf8c.webp"/></p><p>大家都是冲浪人，常言道，“常在河边走，那有不湿鞋”，万一哪天不小心被钓鱼电脑中病毒，浏览器中的密码被一网打尽。因此，上级部门的圣旨还是接下来的好。于是借着这次机会，也给自己的密码管理升升级。</p></div><p style="text-align:right"><a href="https://blog.acg.ng/posts/sec/20240828SJ_MM#comments">看完了？说点什么呢</a></p></div>]]></description><link>https://blog.acg.ng/posts/sec/20240828SJ_MM</link><guid isPermaLink="true">https://blog.acg.ng/posts/sec/20240828SJ_MM</guid><dc:creator><![CDATA[master]]></dc:creator><pubDate>Tue, 27 Aug 2024 18:18:12 GMT</pubDate></item><item><title><![CDATA[域名接入cloudflare后出现ERR_TOO_MANY_REDIRECT错误]]></title><description><![CDATA[<link rel="preload" as="image" href="https://pic.imgdb.cn/item/66c9d545d9c307b7e96a3c74.webp"/><div><blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href="https://blog.acg.ng/notes/1">https://blog.acg.ng/notes/1</a></blockquote><div><p>本博客前端采用Vercel托管，搭建过程中发现一个意料之外的dns解析错误，感觉挺有趣的。
从我拿到域名之后的操作流程如下：</p><ol start="1"><li>从域名提供商那边托管域名到cloudflare；</li><li>在cloudflare控制台中添加一条CNAME记录，用于将域名解析指向Vercel的CNAME服务器：cname.vercel-dns.com；</li><li>在Vervel托管服务中添加域名，完成域名整个解析链。</li></ol><p>理论上来看没有任何问题，但经过一段时间后，发现域名不仅无法正确解析，并且会出现ERR_TOO_MANY_REDIRECT（重定向次数太多）的错误。在经过一系列排查无果后，进F12开发者工具查看发现，域名解析的请求被反复重定向到cloudflare的服务器，这个时候开始怀疑是cloudflare的配置有问题，google后得知，在cloudflare中将SSL/TLS加密模式变更为“完全”或“完全（严格）”即可解决问题。
<img src="https://pic.imgdb.cn/item/66c9d545d9c307b7e96a3c74.webp" alt="20240822SJ_CF_1"/></p><blockquote><p>Flexible：当我们的源网站没有配置 HTTPS 支持时，启用这个选项，Cloudflare 会在回源的时候通过 HTTP 协议访问我们的网站。</p><p>Full：当我们的源网站支持 HTTPS，但是 HTTPS 证书和域名不匹配或者是自签名证书时，Cloudflare 会通过 HTTPS 协议访问源网站，但不会验证证书，也就是说，即使我们的源网站提供的 HTTPS 证书不受浏览器信任，Cloudflare 也会通过 HTTPS 回源网站。</p><p>Full (strict)：当我们的源网站支持 HTTP ，并且证书有效时 (未过期且受信任)。Cloudflare 会通过 HTTPS 协议访问源网站，并在每个请求过程中验证证书。</p></blockquote>
<p>了解了上面各个设置的功能，我们来看一下 Cloudflare 的循环重定向问题是怎么出现的，在 Cloudflare 中开启了 SSL 后，访问网站时出现循环重定向需满足下面两个条件：</p><blockquote><p>SSL 中设置了 Flexible，CDN 以 HTTP 协议回源网站。
源网站支持 HTTPS，并且设置了通过 HTTP 协议访问时，自动跳转到 HTTPS 协议。</p></blockquote>
<p>到这里，问题就出来了，访问 Cloudflare 的 CDN 服务器的时候，是通过 HTTPS 访问的，CDN 访问源网站的时候，是通过 HTTP 访问的，源网站上 HTTP 又自动跳转了 HTTPS，完美的一个循环重定向。重定向的次数多了，浏览器就报出了 ERR_TOO_MANY_REDIRECTS 的错误。</p></div><p style="text-align:right"><a href="https://blog.acg.ng/notes/1#comments">看完了？说点什么呢</a></p></div>]]></description><link>https://blog.acg.ng/notes/1</link><guid isPermaLink="true">https://blog.acg.ng/notes/1</guid><dc:creator><![CDATA[master]]></dc:creator><pubDate>Wed, 21 Aug 2024 17:26:16 GMT</pubDate></item><item><title><![CDATA[缘起]]></title><description><![CDATA[<div><blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href="https://blog.acg.ng/posts/default/20240821BW_YQ">https://blog.acg.ng/posts/default/20240821BW_YQ</a></blockquote><div><p>某天晚上正在论坛中严肃的学习技术<del class="spoiler" title="你知道的太多了">其实就是在吹水</del>，无意间发现有佬正在售卖acg.ng域名，忽然脑子一热，嗯，就像现在这样，从这位佬手中拿下了这个域名。花费一天时间，也终于是把自己从大学羡慕到现在的博客搭建完成了，也算是圆了一个小小心愿？</p><h3 id="">可能会存在的目标</h3><ol start="1"><li>屏退白天杂乱无章的、多如牛毛的琐碎，试着专注于做好一件事</li><li>用写博客的方式记录自己的成长</li><li>倒逼自己抛去无意义的小说、视频，转向有价值的阅读</li><li>分享一些个人在互联网中的所见所闻所感</li></ol><del class="spoiler" title="你知道的太多了">真的会成功吗？</del><h3 id="">不可避免会存在的要素</h3><ol start="1"><li>二次元浓度应该会挺高？<del class="spoiler" title="你知道的太多了">美其名曰充分挖掘域名价值</del></li><li>存在一些个人的胡言乱语</li></ol><p>---
<audio autoPlay="" loop="" id="audioPlayer" controlslist="nodownload" src="https://cs1-78v4.vkuseraudio.net/s/v1/acmp/UtNgQENl0qnC-w574i2Vs2FghSHTT8tMNvBvxlIcG75a8hRTPdlSWPENZj8hVze0fnefosVIvO99WV-oM44_k3PSxZWkwz4-dEhI56SNEQoCb-NLzlGAeAXaa2QaAqdw9F9yzxZ5tndMOMVFMqcfflwiNVGCIxqDk1Jre7CTz-CV6GGpHg.mp3?siren=1" style="position:relative;width:565px;height:54px;left:0px;top:0px"></audio>音乐:ないない - ReoNa</p></div><p style="text-align:right"><a href="https://blog.acg.ng/posts/default/20240821BW_YQ#comments">看完了？说点什么呢</a></p></div>]]></description><link>https://blog.acg.ng/posts/default/20240821BW_YQ</link><guid isPermaLink="true">https://blog.acg.ng/posts/default/20240821BW_YQ</guid><dc:creator><![CDATA[master]]></dc:creator><pubDate>Tue, 20 Aug 2024 03:48:49 GMT</pubDate></item></channel></rss>