GreenVPN逆向尝试


GreenVPN配置文件还原

OD动态分析

本文我们将定位GreenVPN中解密服务器相关信息的反汇编代码,然后还原出解密算法的等价高级语言源码(工程),并解密出远程服务器信息相关的密文。

首先我们在GreenVPN原目录中对配置文件进行查看,发现是加密后的乱码。为了定位到其服务器,我们使用OD进行动态分析,定位解密部分函数

配置文件

若程序想要读取system.ini中的内容,则必须借助windowsApi中的CreateFileA来创建文件句柄。因此,我们可以进入ollydbg中查找主程序Green模块中对CreateFileA的全部调用

右键查找,选中当前模块(标签)或者直接Ctrl+N进入函数列表查找函数

在该界面中直接输入CreateFileA查找对应的函数调用,双击该函数名,查看具体引用情况,发现共有五处调用。

在这五处调用处全部下断点进行分析,并按F9开始运行程序。

断点列表

我们很幸运,第一次断点被触发就遇到了system.ini这个配置文件。

获取配置文件句柄

在这里我们按F8步过,得到返回值句柄为0x334,记住这个重要信息,继续向后运行

得到句柄

后续操作将句柄放在了0x195A84处,同样记住这个指针,句柄调用可能通过指针形式进行

继续运行代码,同时时刻关注句柄指针的调用情况。此处我们发现,在call 内部函数前,将ecx赋值为了句柄指针-0x4的地址,此处很可疑,可能会作为基址进行使用,因此我们F7步入该函数,观察其内部代码

句柄指针被调用

进入0x460162内部以后,我们可以很清楚的看到此处的ReadFile函数。同时我们发现,该函数使用了配置文件的文件句柄,逐字节地将文件内容读取到缓冲区0x195BB8处。

读取配置文件

因此我们右键Buffer,选择在数据窗口中跟随->内存地址,然后F8运行该函数后观察缓冲区内容,发现与system.ini中内容一致

验证数据

由于解密将会使用到缓冲区中的数据,因此我们继续运行代码,观察何时会用到缓冲区中的数据。运行到此处发现代码要访问该缓冲区,观察后续操作

观察调用方式,发现循环:内部操作只有inc和缓冲区逐字节比较,出循环后使用eax-edx,推测此处用于计算配置文件内容length

计算长度

按F4出循环后,观察后续操作,可以看到,借助ecx再次使用了缓冲区中的内容;推测循环中的内容是进行了逐字节的解密(异或+加法)文本解密

我们步出循环,可以发现配置文件内容已经被解密了出来,动态分析到此完毕

构建解密脚本

根据我们获取到的解密方式进行脚本构建,代码如下

import os

def decrypt_file():
    input_file = "./system.ini"
    output_file = "./system.dec"

    # 1. 检查输入文件是否存在
    if not os.path.exists(input_file):
        print(f"❌ 错误:找不到文件 '{input_file}'")
        print("   请检查你的脚本和 system.ini 是否在同一个文件夹里。")
        return

    print(f"✅ 找到文件:{input_file} (大小: {os.path.getsize(input_file)} 字节)")
    print("⏳ 正在逐字节解密...")

    try:
        with open(input_file, 'rb') as f_in, open(output_file, 'wb') as f_out:
            byte_count = 0
            while True:
                byte = f_in.read(1)
                if not byte:
                    break
                b = byte[0]
                # 解密逻辑
                decrypted_byte = ((b ^ 0xBD) + 0x69) & 0xFF
                f_out.write(bytes([decrypted_byte]))
                byte_count += 1
        print(f"✅ 解密完成!共处理 {byte_count} 个字节。")
        print(f"   结果已保存为:{output_file}")

    except PermissionError:
        print(f"❌ 错误:没有权限读取 '{input_file}' 或写入 '{output_file}'。")
    except Exception as e:
        print(f"❌ 发生未知错误:{e}")

if __name__ == "__main__":
    decrypt_file()

查看输出的文件,与动态分析的结果一致,确实成功解密

验证结果


文章作者: Yssx
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Yssx !
评论
  目录