吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 7074|回复: 118
收起左侧

[.NET逆向] 某低代码平台 逆向分析(一)【验证逻辑分析和实践】

  [复制链接]
pjy612 发表于 2023-4-17 16:27
本帖最后由 pjy612 于 2025-11-13 22:23 编辑

某低代码平台 逆向分析(一)【验证逻辑分析和实践】

前情提要

虽然之前一直有看到 低代码 低代码的,但是具体是个啥还不太清楚...
这不巧了么...前两期的嘉宾的其他产品里也有个低代码...
但是这羊毛不能只逮着一只薅啊...
所以咱还是在水区发了个帖子,看看大伙儿对这类玩意儿的兴趣程度...
万一很感兴趣,那咱就别发了...
但是看样子大伙儿好像并没啥兴趣...
这样拿出来分析就没啥压力了呢~
然后 网上搜了下 发现 破解版还不少
既然别人都能破解了,那咱们应该也可以试着分析分析吧...
这下 不算是nuget包了,也不是 "简单的js"(论坛web逆向大牛太多,咱的分析帖感觉都上不了台面)
而是实打实的.Net应用了!
希望大伙儿能学到点别的思路...

_(:3」∠)_ 这波弄完基本就真掏空了...  

Ps.这次图片高达35张又创新高... 难道以后要出视频?!

嘉宾介绍

链接
国外官网 aHR0cHM6Ly93d3cuZm9yZ3VuY3kubmV0Lw==
国内官方 aHR0cHM6Ly93d3cuZ3JhcGVjaXR5LmNvbS5jbi9zb2x1dGlvbnMvaHVvemlnZQ==
国内文档 aHR0cHM6Ly9oZWxwLmdyYXBlY2l0eS5jb20uY24vZGlzcGxheS9IdW9aaUdlOA==

准备工作

先去国内官方下载程序吧,分客户端和服务端...
然后简单登陆看看
001.png
没啥毛病 开始分析

开始分析

随便写个假码试试
005.png
emmm 有在线验证啊,但是 文档里面有写离线验证,那咱们研究下怎么触发吧。
看着像个MVC的程序,那么看看启动程序吧。
003.png
默认情况启动了两个进程。
再看看服务
002.png
那么 实际 后台项目 就是 ForguncyUserServiceConsole.dll 了。
扔到 dnspy 里面瞧瞧
006.png
有控制流混淆啊... 先试试运气吧,扔 de4dot 里面看看处理完还能不能跑。
另外因为如果要经常改程序集,就不用服务启动了 停掉服务,手动运行 ForguncyWorkerService.exe 吧。
全默认参数 走你┏ (゜ω゜)=☞
007.png
然后 把处理完的文件名改回 dll,重跑一下看看,能启动最好,不能启动就只能带混淆分析了。。。
008.png
处理完就清晰多了,但是能跑起来吗? 试试先
009.png
看来没问题!那之后的DLL遇到要分析的都可以先这么处理一下了!
但是这个dll明显不是 MVC的架构,
所以实际启动还在别的里面...
这里面有明显的标记 Forguncy.UserService2
然后实际经过一番定位后 也确定是 它。
010.png
那么 也先给它去混淆一下 然后继续定位。
011.png
012.png
013.png
其中 构建请求数据 和 在线验证 又都在 CommonUtilities 里面
014.png
那么我们也处理一下dll吧...
结果处理后无法启动 提示 从 CommonUtilities 中 字段找不到。
看来不能用默认选项处理 有的名称需要保持不变 所以加上 --dont-rename 重新处理下。
这次就正常了。
继续分析。

//构建注册请求对象
internal static Dictionary<string, object> a(string A_0, string A_1, string A_2 = null)
{
        A_0 = A_0.Replace("-", "");
        ForguncySystemInfo forguncySystemInfo = Injectors.GetForguncySystemInfo();
        string[] array = new string[]
        {
                forguncySystemInfo.ComputerId,
                A_0,
                Environment.MachineName,
                DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                A_1,
                forguncySystemInfo.OSInfo,
                forguncySystemInfo.HDInfo,
                forguncySystemInfo.CPUInfo,
                A_2
        };
        string text = string.Join("\r\n", array);
        List<string> list = ac.d(aa.a);
        string text2 = string.Format("<{0}><{1}>{2}</{1}><{3}>{4}</{3}></{0}>", new object[]
        {
                list[0],
                list[1],
                ac.a(aa.c),
                list[2],
                ac.c(aa.b)
        });
        text = EncryptDecryptHelper.EncryptByXmlPublicKey(text, text2); //这里有用公钥对数据加密,所以这里得动
        Dictionary<string, object> dictionary = new Dictionary<string, object>();
        dictionary.Add("data", text);
        if (ResourceHelper.IsChinese())
        {
                dictionary.Add("versionLang", "cn");
        }
        else if (ResourceHelper.IsKorean())
        {
                dictionary.Add("versionLang", "kr");
        }
        else if (ResourceHelper.IsJapanese())
        {
                dictionary.Add("versionLang", "ja");
        }
        else
        {
                dictionary.Add("versionLang", "en");
        }
        return dictionary;
}
//在线验证部分
internal class ab : z
{
        // Token: 0x060006C6 RID: 1734 RVA: 0x00005CBD File Offset: 0x00003EBD
        internal static string a()
        {
                if (ResourceHelper.IsJapanese())
                {
                        return "https://forguncylicenseonlineapp.azurewebsites.net/";
                }
                if (ResourceHelper.IsKorean())
                {
                        return "http://211.171.250.147:808/";
                }
                if (ResourceHelper.IsChinese())
                {
                        return "http://forguncyactiveservice.grapecity.com.cn/";
                }
                return "https://activation.forguncy.net/";
        }

        // Token: 0x060006C7 RID: 1735 RVA: 0x00005CEB File Offset: 0x00003EEB
        ActiveResult z.a(Dictionary<string, object> A_0, ProxySettings A_1)
        {
                if (!ResourceHelper.IsChinese() && !ResourceHelper.IsEnglish())
                {
                        return this.a("Active", A_0, A_1);
                }
                return this.a("ActiveV8", A_0, A_1);
        }

        // Token: 0x060006C8 RID: 1736 RVA: 0x00005D16 File Offset: 0x00003F16
        ActiveResult z.b(Dictionary<string, object> A_0, ProxySettings A_1)
        {
                if (!ResourceHelper.IsChinese() && !ResourceHelper.IsEnglish())
                {
                        return this.a("Deactive", A_0, A_1);
                }
                return this.a("DeactiveV8", A_0, A_1);
        }

        // Token: 0x060006C9 RID: 1737 RVA: 0x00013A94 File Offset: 0x00011C94
        ActiveResult z.c(Dictionary<string, object> A_0, ProxySettings A_1)
        {
                ActiveResult activeResult;
                try
                {
                        string text = EncryptDecryptHelper.DecryptByPublicKey(A_0["data"].ToString(), SystemConfigDef.PlugInAndIPPPublicKey);
                        activeResult = new ActiveResult
                        {
                                Success = true,
                                Result = EncryptDecryptHelper.EncryptByPublicKey(text, SystemConfigDef.PlugInAndIPPPublicKey)
                        };
                }
                catch
                {
                        activeResult = this.a("CheckLicense", A_0, A_1);
                }
                return activeResult;
        }

        // Token: 0x060006CA RID: 1738 RVA: 0x00005D41 File Offset: 0x00003F41
        private ActiveResult a(string A_0, Dictionary<string, object> A_1, ProxySettings A_2)
        {
                return JsonConvert.DeserializeObject<ActiveResult>(ServiceVisitor.CreateServiceVisitor(ab.a()).CallMethodToGetResultString(A_0, A_1, A_2));
        }

        // Token: 0x060006CB RID: 1739 RVA: 0x000024DE File Offset: 0x000006DE
        public ab()
        {
        }
}

如果我们想不走在线流程 根据 注册部分的代码 是不是 我们直接 抛异常就行了???

internal static ActiveResult smethod_25(string string_1, string string_2, ProxySettings proxySettings_0)
{
        Dictionary<string, object> dictionary = aa.a(string_1, string_2, "8.0.105.0");
        ActiveResult activeResult;
        try
        {
                //throw new Execption(); //这里直接扔异常
                activeResult = aa.a().d(dictionary, proxySettings_0);
        }
        catch (Exception)
        {
                activeResult = Class229.smethod_30(dictionary["data"] as string);
        }
        return activeResult;
}

我们实践一下。
015.png
016.png
emmmm ... 是不是太简单了?
万一遇到 不能直接改和编译的情况呢???
得上IL修改 咱们撤销一下再来一次。
017.png
我们得在call之前给他 扔一个异常。
018.png
然后保存。
019.png
和我们想的有点不一样。。。
我们重新打开 IL 切到异常处理模块。
我们加的代码是 5 ,但是 异常处理 开始位置是 7,所以我们改改。
020.png



好了 对了。
重跑看看。
尴尬 报错了。。。
021.png
咱们来附加调试看看。。。
022.png
再点下试试。。。
023.png
断下来了。。。  但是咱码呢???码没了?!
看看堆栈
024.png
025.png
得。。。又是去混淆的锅,看来 Forguncy.UserService2 处理时 也要加上 --dont-rename
上面几步重新弄一下。稍等。。。
026.png
看吧。。。就说没那么简单吧。。。得上IL大法。。。
再附加调试一下。
027.png
咱又有码了!放行!
028.png
029.png
能稳定触发离线注册了。
开始分析离线流程。
030.png

[HttpPost]
public ResultData OffLineActive([FromBody] OffLineActiveParam param)
{
        string content = param.content;
        ManagementPageService managementPageService = new ManagementPageService(base.DBContext, this.User);
        ResultData resultData = managementPageService.a(Privileges.ActiveBaseServerLicense);
        if (resultData != null)
        {
                return resultData;
        }
        ActiveResult activeResult = Forguncy.UserService2.Controllers.f.e(content);
        return new ResultData
        {
                Message = (activeResult.Success ? activeResult.Result : activeResult.ErrorMessage),
                Result = activeResult.Success
        };
}
//A_0 离线激活码
internal static ActiveResult e(string A_0)
{
        ActiveResult activeResult;
        try
        {
                string[] array = A_0.Split("|", StringSplitOptions.None);
                string text = array[0];
                ag ag = Forguncy.UserService2.Controllers.f.a(text); //解析码转实体
                if (ag == null)
                {
                        activeResult = ActiveResult.Error(Resources.LicenseActiveResultError_KeyError);
                }
                else if (ag.ComputerName != Environment.MachineName)//ComputerName = Environment.MachineName
                {
                        activeResult = ActiveResult.Error(Resources.LicenseActiveResultError_MachineNameError);
                }
                else if (ag.OSID != ar.b()) OSID = 某个值 可以调试一下
                {
                        activeResult = ActiveResult.Error(Resources.LicenseActiveResultError_ComputerIdError);
                }
                else
                {
                        //剩下的都是在写码了
                        Forguncy.UserService2.Controllers.f.a(array[0], Forguncy.UserService2.Controllers.f.g(), ag.SerialKey.Key);
                        CommonUtilities.aa.a(ag.SerialKey.Key, ag.Credential);
                        if (array.Length == 3 && ResourceHelper.IsChinese())
                        {
                                Forguncy.UserService2.Controllers.f.a(array[1], Forguncy.UserService2.Controllers.f.e(), ag.SerialKey.Key);
                                Forguncy.UserService2.Controllers.f.a(array[2], Forguncy.UserService2.Controllers.f.f(), ag.SerialKey.Key);
                        }
                        activeResult = new ActiveResult(Resources.LicenseActiveResult_ActiveSuccess);
                }
        }
        catch (Exception ex)
        {
                TraceHelper.TraceException(ex, null, "OfflineActive");
                activeResult = ActiveResult.Error(Resources.LicenseActiveResult_ActiveFailed);
        }
        return activeResult;
}
//那我们着重分析下 解码  
//Forguncy.UserService2.Controllers.f.a(text)
private static ag a(string A_0)
{
        return af.b(CommonUtilities.aa.a(A_0));
}
//CommonUtilities.aa.a(A_0)
internal static Stream a(string A_0)
{
        MemoryStream memoryStream = new MemoryStream();
        StreamWriter streamWriter = new StreamWriter(memoryStream);
        streamWriter.Write(A_0);
        streamWriter.Flush();
        memoryStream.Position = 0L;
        return memoryStream;
}
//af.b
internal static ag b(Stream A_0)
{
        if (SystemConfigDef.IsCloudServer) // 我们不用这个 所以走下面 
        {
                ag ag;
                using (StreamReader streamReader = new StreamReader(A_0))
                {
                        ag = JsonConvert.DeserializeObject<ag>(EncryptDecryptHelper.DecryptByPublicKey(streamReader.ReadToEnd().Trim(), SystemConfigDef.CloudSitesLicRsaPublicKey));
                }
                return ag;
        }
        return af.a(A_0);//实际逻辑在这儿
}
//af.a(A_0)
//A_0 离线激活码
private static ag a(Stream A_0)
{
        string text = null;
        string text2 = null;
        af.d = null;
        ag ag2;
        try
        {
                using (StreamReader streamReader = new StreamReader(A_0))
                {
                        for (string text3 = streamReader.ReadLine(); text3 != null; text3 = streamReader.ReadLine())
                        {
                                if (text3.StartsWith("F1="))
                                {
                                        text = text3;
                                }
                                else if (text3.StartsWith("F2="))
                                {
                                        text2 = text3;
                                }
                                if (text != null && text2 != null)
                                {
                                        break;
                                }
                        }
                        //由上面逻辑分析,码由两部分构成 是字符串 两行
                        //F1=xxx
                        //F2=xxx
                        if (text != null && text2 != null)
                        {
                                byte[] array = EncryptDecryptHelper.AESDecrypt(Convert.FromBase64String(text.Substring("F1=".Length)), ae.c, ae.d, CipherMode.CBC, PaddingMode.PKCS7);
                                ag ag = ag.a(array);//这里直接是 JSON 反序列化 所以 原始 F1 应该为 ASE(鉴权对象的JSON)
                                if (ag == null)
                                {
                                        return null;
                                }
                                //这个是解密出一个公钥
                                string @String = Encoding.ASCII.GetString(EncryptDecryptHelper.AESDecrypt(ae.e, ae.c, ae.d, CipherMode.CBC, PaddingMode.PKCS7));
                                if (string.IsNullOrWhiteSpace(@string))
                                {
                                        return null;
                                }
                                using (RSACryptoServiceProvider rsacryptoServiceProvider = new RSACryptoServiceProvider(2048))
                                {
                                        rsacryptoServiceProvider.FromXmlString(@string);//导入公钥
                                        byte[] array2 = array;
                                        byte[] array3 = Convert.FromBase64String(text2.Substring("F2=".Length));
                                        //对 鉴权对象的JSON 进行鉴权,所以 F2=sing(鉴权对象的JSON)
                                        if (rsacryptoServiceProvider.VerifyData(array2, CryptoConfig.MapNameToOID("SHA1"), array3))
                                        {
                                                af.d = new bool?(true);
                                                return ag;
                                        }
                                        af.d = new bool?(false);
                                        return null;
                                }
                        }
                        ag2 = null;
                }
        }
        catch (Exception)
        {
                ag2 = null;
        }
        return ag2;
}

那么答案就有了。
我们 把这个AES提取一下,然后 RSA 就用自己生成一套。能对上就行。
ag 对象 我们也抄一下。

开工 (替换密钥+离线激活码实现)

由于是首次处理,所以我们直接走爆破,毕竟爆破成功的话,后续才好根据特征写自动补丁。
那么通过我们上面的分析,为了能正常通信,那么至少有两点。
离线请求码的构建部分 和 解析离线码的密钥 我们都要改。
大方点我们直接塞私钥。
031.png
032.png
然后 我们生成一个离线码解析看看。
033.png
解码后的信息

90855*********************58d9
6666666666666666
机器名
2023-04-17 13:24:47
server
Microsoft Windows 10 Enterprise
\\.\PHYSICALDRIVE0
11th Gen Intel(R) Core(TM) i5-1145G7 @ 2.60GHz,BFEBFBFF000806C1
8.0.105.0

然后 激活码实体结构为
(一些更细节的分析,比如哪个key要填什么值,为什么要那么填,具体怎么找的。
由于篇幅限制 这里就直接给答案了,有兴趣的可以自己去分析具体的检测)


class LicenseInfo
{
    public string SerialKeyID { get; set; }  //没太多意义 52pojie
    public KeyInfo SerialKey { get; set; }   //子对象
    public string OSID { get; set; }         //line[0]
    public string Credential { get; set; }   //没太多意义 52pojie
    public string ComputerName { get; set; } //line[2]
    public string VersionString { get; set; }//line[8]
}
class KeyInfo
{
    public string Key { get; set; } //激活时填的码 line[1];
    public string DevelopmentKey => this.Key;
    public int KeyType { get; set; } //-3  CommonUtilities.SerialKeyType.CNServerAndUser
    public DateTime Duration { get; set; } = TimeZoneInfo.ConvertTimeToUtc(DateTime.MaxValue); //期限
    public bool IsTerm { get; set; } = false; //是否有期限
    public bool Enabled { get; set; } = true;
    public bool isComputerNameVerify { get; set; } = false;//是否验证机器名
    public int Version { get; set; } // -7779 ForguncyVersion.LicenseVersionNumber_CN
    public int PageNumber { get; set; } //页面数什么的 不填最大
    public string ExtendInfos { get; set; } //人数什么的 不填最大
    public bool ConcurrentUser { get; set; } = true; //是否并发
    public bool IncludeReport { get; set; } = true;  //是否报表
}
{"SerialKeyID":"52pojie","SerialKey":{"Key":"666666666666666666666666","DevelopmentKey":"666666666666666666666666","KeyType":-3,"Duration":"\/Date(253402271999999)\/","IsTerm":false,"Enabled":true,"isComputerNameVerify":false,"Version":-7779,"PageNumber":0,"ExtendInfos":null,"ConcurrentUser":true,"IncludeReport":true},"OSID":"*********","Credential":"52pojie","ComputerName":"机器名","VersionString":"8.0.105.0"}

见证奇迹的时刻!!!  


啊咧?!但是Σ(っ °Д °;)っ 提交成功了...为啥还是空白的?!?!
没有弹错误提示啊?
看来还有🕳(坑)
咱们来看 ManagementPage/LicenseList 接口。

[HttpGet]
public IActionResult LicenseList()
{
        Forguncy.UserService2.Models.a a = Forguncy.UserService2.Controllers.f.d(base.DBContext);
        return this.a("LicenseList", a);
}
//Forguncy.UserService2.Controllers.f.d(base.DBContext);
internal static Forguncy.UserService2.Models.a d(UserServiceDBContext A_0)
{
        Forguncy.UserService2.Models.a a = Forguncy.UserService2.Controllers.f.d.Get(Forguncy.UserService2.Controllers.f.e) as Forguncy.UserService2.Models.a;
        if (a != null)//读缓存有必要 调试时 手动赋值为null
        {
                return a;
        }
        List<Forguncy.UserService2.Controllers.f.a> list = Forguncy.UserService2.Controllers.f.g(null);
        Forguncy.UserService2.Models.a a2 = new Forguncy.UserService2.Models.a();
        a2.ComputerName = Environment.MachineName;
        new Forguncy.UserService2.Controllers.f.i().bk(list.FirstOrDefault<Forguncy.UserService2.Controllers.f.a>(), a2).bl();
        new Forguncy.UserService2.Controllers.f.n().bk(list.FirstOrDefault<Forguncy.UserService2.Controllers.f.a>(), a2).bl();
        new Forguncy.UserService2.Controllers.f.s().bk(list.FirstOrDefault<Forguncy.UserService2.Controllers.f.a>(), a2).bl();
        new Forguncy.UserService2.Controllers.f.x().bk(list.FirstOrDefault<Forguncy.UserService2.Controllers.f.a>(), a2).bl();
        if (AutoTestIndicator.IsAutoTest)
        {
                a2.AllowUserCount = int.MaxValue;
        }
        Forguncy.UserService2.Controllers.f.d.Add(Forguncy.UserService2.Controllers.f.e, a2, new TimeSpan(1, 0, 0));
        return a2;
}
//Forguncy.UserService2.Controllers.f.g(null);
internal static List<Forguncy.UserService2.Controllers.f.a> g(string A_0 = null)
{
        string text = Forguncy.UserService2.Controllers.f.f(A_0);//获取License存放的路径
        return Forguncy.UserService2.Controllers.f.a(text, typeof(Forguncy.UserService2.Controllers.f.d));
}
//Forguncy.UserService2.Controllers.f.a
private static List<Forguncy.UserService2.Controllers.f.a> a(string A_0, Type A_1)
{
        if (!Directory.Exists(A_0))
        {
                return new List<Forguncy.UserService2.Controllers.f.a>();
        }
        string[] files = Directory.GetFiles(A_0); //通过路径获取所有的离线key信息
        FileInfo[] array = new FileInfo[files.Length];
        for (int i = 0; i < files.Length; i++)
        {
                array[i] = new FileInfo(files[i]);
        }
        Array.Sort<FileInfo>(array, new Comparison<FileInfo>(Forguncy.UserService2.Controllers.f.<>c.<>9.a));
        HashSet<string> hashSet = new HashSet<string>();
        List<Forguncy.UserService2.Controllers.f.a> list = new List<Forguncy.UserService2.Controllers.f.a>();
        foreach (FileInfo fileInfo in array)
        {
                a3 a = Forguncy.UserService2.Controllers.f.h(fileInfo.FullName); //实际解析Key
                Forguncy.UserService2.Controllers.f.b b = Forguncy.UserService2.Controllers.f.f.a(a, A_1);
                //后续一些验证
                if (Forguncy.UserService2.Controllers.f.a(b) && (a == null || a.SerialKey == null || a.SerialKey.Key == null || !hashSet.Contains(a.SerialKey.Key)))
                {
                        if (a != null)
                        {
                                hashSet.Add(a.SerialKey.Key);
                        }
                        Forguncy.UserService2.Controllers.f.a a2 = new Forguncy.UserService2.Controllers.f.a
                        {
                                ImportDate = fileInfo.CreationTime,
                                License = a,
                                AssociatedLicenseFile = fileInfo.FullName
                        };
                        list.Add(a2);
                }
        }
        return list;
}
//Forguncy.UserService2.Controllers.f.h(fileInfo.FullName)
private static a3 h(string A_0)
{
        if (!File.Exists(A_0))
        {
                TraceHelper.WriteLicenseException("license file can't find");
                TraceHelper.WriteLicenseException("filePath : " + A_0);
                return null;
        }
        a3 a2;
        try
        {
                using (FileStream fileStream = File.OpenRead(A_0))
                {
                        a3 a = a2.b(fileStream);
                        if (a == null)
                        {
                                TraceHelper.WriteLicenseException("The Readed license info is null");
                        }
                        a2 = a;
                }
        }
        catch (Exception ex)
        {
                TraceHelper.WriteLicenseException("Read license file failed");
                TraceHelper.TraceException(ex, null, "GetLicenseInfoFromFile");
                a2 = null;
        }
        return a2;
}
//a2.b(fileStream) 见下图

034.png
看来不止一处 需要 修改 RSA 密钥啊。。。 手动改改再重启看看。。。

哈!搞定收工!

结果展示

035.png

下期预告

  • 客户端虽然是免费的,但是使用前还是会有个激活码验证,咱们也试试🔪掉吧~  

  • 插件市场好丰富,纳尼?里面竟然还有收费的?而且价格好像都赶超软件本体了?那不得试试能不能白嫖了!🔪了🔪了!  

  • 发布功能是不是正常,咱们还没测呢!

  • 不看不知道 一看吓一跳,应用里竟然有检测白嫖的暗桩?!拿网上破解版来干坏事的小伙伴小心会遭重哟!

  • 虽然这个应用混淆不复杂也能改代码,但是校验的点有些多。。。
    不小心漏了就要继续分析,而且每次都手动改exe或dll是不是很麻烦?
    对这种能改的程序 有没有什么偷懒的方案,这种相同的逻辑能不能通杀?比如 Hook 一下?  

感兴趣的话 给咱点免费评分呗... 咱好有动力抓紧码字啊...

免费评分

参与人数 33威望 +2 吾爱币 +130 热心值 +30 收起 理由
blueskys + 1 + 1 我很赞同!
box78519 + 1 + 1 用心讨论,共获提升!
猫吃 + 1 我很赞同!
wanjingbo + 1 + 1 谢谢@Thanks!
gqdsc + 1 + 1 这个我喜欢,感谢分享大神
我不是旧时 + 1 + 1 谢谢@Thanks!
BlueQAQ + 1 + 1 谢谢@Thanks!
3303B + 1 我很赞同!
笙若 + 1 + 1 谢谢@Thanks!
b12312312 + 1 + 1 热心回复!
喜子12131 + 1 + 1 已经处理,感谢您对吾爱破解论坛的支持!
qet006 + 1 + 1 用心讨论,共获提升!
fxxxysh010 + 1 + 1 谢谢@Thanks!
bnjzzheng + 1 我很赞同!
yeguochuchen + 1 热心回复!
onlywey + 1 + 1 用心讨论,共获提升!
byxifan + 1 + 1 我很赞同!
fengbolee + 2 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
blicfan + 1 + 1 用心讨论,共获提升!
Hmily + 2 + 100 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
卑鄙的我 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
HAINING + 1 + 1 我很赞同!
wapjwsy + 1 + 1 用心讨论,共获提升!
三岁就会写BUG + 1 + 1 期待下一期!
LYTLYT + 1 谢谢@Thanks!
mscsky + 1 + 1 热心回复!
helian147 + 1 + 1 热心回复!
dialga + 1 谢谢@Thanks!
powerpanda + 1 用心讨论,共获提升!
侃遍天下无二人 + 4 + 1 用心讨论,共获提升!
lml0126 + 1 谢谢@Thanks!
3yu3 + 1 + 1 用心讨论,共获提升!
leommm + 1 我很赞同!

查看全部评分

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

 楼主| pjy612 发表于 2023-4-19 09:14
HAINING 发表于 2023-4-19 08:56
大佬,可以提供一下你用的Easy_de4dot吗?按照你的教程,脱壳不对啊!

de4dot-All-Version de4dot多版本合集 含多合一拖拽gui工具箱
https://www.52pojie.cn/thread-1595502-1-1.html
(出处: 吾爱破解论坛)
 楼主| pjy612 发表于 2023-4-19 09:21
本帖最后由 pjy612 于 2023-4-19 09:39 编辑
HAINING 发表于 2023-4-19 09:17
感谢大佬,今天按照你的流程试试,客户端能发布吗?

手动改的话 客户端里面也有个dll 要改


帖子内第三处 因为和第二处逻辑一样 所以没具体说明。

找到第三处改就行了。。。
第一处是构建离线请求,不改的话 没法解析。
第二处是离线码解码,不改的话不识别。
第三处和第二处逻辑是一样的,但是位于不同的dll。也是离线码解码。

客户端部分 和 发布后的站点服务 里面也都相同的离线码解码。手动改的的话 这几个地方都要改。

PS.瞟了一眼大佬历史的 cm 直接吓退。
lg560852 发表于 2023-4-17 16:41
这个厉害了,现在低代码都是趋势,开发都要被运维顶替了,打工人何苦为难打工人。。
 楼主| pjy612 发表于 2023-4-17 16:27
沙发自己坐~
hisokou 发表于 2023-4-17 16:52
这个可以有,以后都要chagpt来顶替了
wangwh27 发表于 2023-4-17 17:14
好复杂啊,期待楼主的通杀方案。
无敌小儿 发表于 2023-4-17 17:21
真厉害啊,大牛
yangxinchina22 发表于 2023-4-17 17:53
厉害大佬
glovy 发表于 2023-4-17 18:11
老大牛。学习了。感谢感谢
xmtt2008 发表于 2023-4-17 18:19
感谢分享!!
liduowu 发表于 2023-4-17 18:30
太牛了,顺便把WYN也弄一下哈
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2026-1-15 04:41

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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