BlackNWhite 发表于 2015-8-27 19:55

对某校园网跨域软件的逆向分析和重实现

上学期校园网里突然流行起一款免费的跨域软件(威皮恩),速度非常不错,下载能达到1M/S,但是只能在校园网范围内使用。
最近放假在家,想要翻墙下一款软件,苦于找不到好的威皮恩,所以就想到是不是能把校园网的跨域软件弄到家里来用用。

用DIE查看程序的编写语言和加壳情况(对于壳和混淆的分析我还是新手,只能靠工具,还得加油学习)



发现程序使用.NET服务框架写的,用.NET Reactor加的壳。考虑脱壳后反编译试试。

De4Dot对.NET Reactor的脱壳效果一向不错,考虑直接用它试试


(为了尊重程序作者的权益,程序名已打码,文章中也不会出现程序名)

发现成功了,不知道脱壳玩不完全,但是可以尝试反编译了,就是不知道反编译之后的效果会怎么样。

直接上DotPeek试试


发现反编译后的代码特别干净整齐,应该是成功了,既然反编译成功了,我也就不甘于之解决校园网外的连接问题了。
由于改程序在连接威皮恩时没有要求输入用户凭证,是一键式连接的,怀疑在程序中存有服务器信息和账号密码信息。

上面两款软件已经帮我把它的代码还原得这么干净整齐了,我当然不能浪费了这个资源。

怀疑程序作者在写程序的时候方法使用了"connect"字样,直接搜索试试,得到了下面的代码块:



发现服务器地址了:"jp" + MainWindow.fastest_server.ToString() + ".toven.info"
怀疑程序在启动的时候ping了一下威皮恩服务器,然后按延迟排序,选了延迟最小的服务器来连接。
按格式来看,不用找fastest_server变量了,它肯定是int型。那么按这个格式ping一下服务器试试:



ping到"jp9.toven.info"的时候发现ping不通了,那么怀疑服务器是"jp1"到"jp8"。

这时候服务器地址也有了,只差账服务器的连接凭证了,再在源码中找找,搜"user"和"pass"字符居然一时半会没找到账号密码。
耐下心来,从头开始找,发现了这么个东西:


看到链接中有"reg.php"和"user"的字符,怀疑是通过程序向reg.php页面发送了http请求申请了一个账号,那么打开链接试试:


打开发现是这么个页面,发现注册不用填写验证码,而且“初始预付服务”中有“免费账户”的选项。随便注册一个免费账户后发现免费用户是三十分钟的试用时间,用完之后就只能付费使用了。

这时候能得出结论了:这个校园网跨域软件用的不是用自己的服务器,而是别人威皮恩产品提供的试用服务,通过HTTP请求申请账号(申请账号不要求填写验证码,这个实现起来非常简单),三十分钟一断,断开之后再申请一个,重新连接。

得出这个结论之后,我决定利用作者的成果来写一个自己用的威皮恩(其实是用了别人的服务器)

查看网页的元素发现表单的命名也非常规则,得出了申请账号的post格式:
http://user.tosver.cn/reg.php?cont=store_user&lang=Chinese&username=用户名&password1=密码&password2=再次输入密码&mobile&email&srvid=1&textarea=%E6%8F%90%E7%A4%BA%EF%BC%9A%E8%AF%B7%E4%BB%94%E7%BB%86%E9%98%85%E8%AF%BB%E4%BB%A5%E4%B8%8B%E6%9D%A1%E6%AC%BE%EF%BC%8C%E5%86%8D%E6%B3%A8%E5%86%8C%E5%B8%90%E5%8F%B7%E3%80%82%E4%BD%BF%E7%94%A8%E6%9C%AC%E7%BD%91%E7%AB%99%E8%A1%A8%E7%A4%BA%E6%82%A8%E5%90%8C%E6%84%8F%E9%81%B5%E5%AE%88%E8%BF%99%E4%BA%9B%E6%9D%A1%E6%AC%BE%E5%92%8C%E6%9D%A1%E4%BB%B6%E3%80%82%E5%A6%82%E6%9E%9C%E6%82%A8%E4%B8%8D%E6%8E%A5%E5%8F%97%E8%BF%99%E4%BA%9B%E6%9D%A1%E6%AC%BE%EF%BC%88%E2%80%9C%E6%9D%A1%E6%AC%BE%E2%80%9D%EF%BC%89%EF%BC%8C%E8%AF%B7%E5%8B%BF%E6%B3%A8%E5%86%8C%E3%80%82&acceptterms=1&adduser=%E5%88%9B%E5%BB%BA%E8%B4%A6%E6%88%B7

username参数是用户名,password1是密码,password2是确认密码输入,srvid是用户类型,1是免费用户,然后是一大串用户协议之类的内容(不知道这个参数有没有必要,总是先弄上去),acceptterms是接受用户协议,给它传递个1应该就是接受了吧。

随便弄一个用户名和密码用postman来post这个页面发现返回了注册成功的页面


那么现在就能写一个程序来方便以后使用了。



界面就这样吧,毕竟是自己用的简易威皮恩

接下来实现账号密码申请功能:

先是post方法:
public static string PostWebRequest(string postUrl, string paramData, Encoding dataEncode)
{
    string ret = string.Empty;
    try
    {
      byte[] byteArray = dataEncode.GetBytes(paramData);
      HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create(new Uri(postUrl));
      webReq.Method = "POST";
      webReq.ContentType = "application/x-www-form-urlencoded";

      webReq.ContentLength = byteArray.Length;
      Stream newStream = webReq.GetRequestStream();
      newStream.Write(byteArray, 0, byteArray.Length);
      newStream.Close();
      HttpWebResponse response = (HttpWebResponse)webReq.GetResponse();
      StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.Default);
      ret = sr.ReadToEnd();
      sr.Close();
      response.Close();
      newStream.Close();
    }
    catch (Exception ex)
    {
      Console.WriteLine(ex.Message);
      return "Error";
    }
    return ret;
}

然后是账号密码部分:
用一串10位的随机数来填充账号部分,短时间内应该不会有重复的用户名:
private string CreateUsername()
{
    string username = "crac";
    Random random = new Random();

    for (int i = 0; i < 10; ++i)
    {
      username += random.Next(0, 9).ToString();
    }

    return username;
}


密码就随便在键盘上敲一下吧,就用dsDW4er2342

然后是账号密码申请方法:
public bool Register()
{
    string password = "dsDW4er2342";
    string username = CreateUsername();

    string postUrl = "http://user.tosver.cn/reg.php";
    string usernamePart = "cont=store_user&lang=Chinese&username=" + username + "&";
    string passwordPart = "password1=" + password + "&password2=" + password + "&";
    string otherPart = "mobile&email&srvid=1&textarea=%E6%8F%90%E7%A4%BA%EF%BC%9A%E8%AF%B7%E4%BB%94%E7%BB%86%E9%98%85%E8%AF%BB%E4%BB%A5%E4%B8%8B%E6%9D%A1%E6%AC%BE%EF%BC%8C%E5%86%8D%E6%B3%A8%E5%86%8C%E5%B8%90%E5%8F%B7%E3%80%82%E4%BD%BF%E7%94%A8%E6%9C%AC%E7%BD%91%E7%AB%99%E8%A1%A8%E7%A4%BA%E6%82%A8%E5%90%8C%E6%84%8F%E9%81%B5%E5%AE%88%E8%BF%99%E4%BA%9B%E6%9D%A1%E6%AC%BE%E5%92%8C%E6%9D%A1%E4%BB%B6%E3%80%82%E5%A6%82%E6%9E%9C%E6%82%A8%E4%B8%8D%E6%8E%A5%E5%8F%97%E8%BF%99%E4%BA%9B%E6%9D%A1%E6%AC%BE%EF%BC%88%E2%80%9C%E6%9D%A1%E6%AC%BE%E2%80%9D%EF%BC%89%EF%BC%8C%E8%AF%B7%E5%8B%BF%E6%B3%A8%E5%86%8C%E3%80%82&acceptterms=1&adduser=%E5%88%9B%E5%BB%BA%E8%B4%A6%E6%88%B7";

    if (PostWebRequest(postUrl, usernamePart + passwordPart + otherPart, Encoding.UTF8).IndexOf("账户已经创建") != -1)
    {
      this.username = username;
      this.password = password;
      return true;
    }
    else
    {
      postUrl = "http://user.tovens.com/reg.php";
      if (PostWebRequest(postUrl, usernamePart + passwordPart + otherPart, Encoding.UTF8).IndexOf("账户已经创建") != -1)
            return true;
      else
            return false;
    }
}

我将它们写在了一个类中,类中有public string型的username和password属性,构造方法中调用Register()方法,
若Register方法返回True则该类对象可用,若返回False则username和password属性为null,该对象不可用。

接下来用DotRas库来实现威皮恩连接功能,这里用到了别人写的VPNHelper类,用来辅助调用DotRas库的方法来创建和链接威皮恩。我重载了一个构造方法,使它接受一个UsernameKeeper类对象(就是上面写的用来申请账号的类)来初始化vpnHelper类对象的账号密码以连接威皮恩。
这个类就不贴出来了,代码太长。

直接到创建和链接威皮恩部分:
private void buttonConnect_Click(object sender, EventArgs e)
{
      UsernameKeeper usk = new UsernameKeeper();
      vpnHelper = new VPNHelper("jp1.toven.info", "EasyVPN", usk);

       vpnHelper.CreateOrUpdateVPN();
    vpnHelper.TryConnectVPN();
}

然后就搞定了,以后就能在任何地方一键连接威皮恩了。至于半小时断一次的解决方案,我认为每20s ping一次twitter.com是可行的,如果Ping不通的话就断开重连。
为了使文章不过于冗长,就先不实现更多功能了。

至此,整个过程结束。

(由于规定,我就不放出原校园网跨域软件和编译后的威皮恩及完整源码了,只分享思路和一小部分关键部分的C#语言实现,有兴趣的朋友可以自己用任何其他的语言将其完整实现写出来)

XhyEax 发表于 2015-8-28 16:52

然而网址还是没打码。。。。{:1_925:}

楼主,经我测试,那个postdata里的很多参数都可以不带,进行注册。
只需要一下参数:
username=&password1=&password2=&srvid=1&acceptterms=1
///依次是:用户名密码 重复密码 服务id(1为免费) 是否接受条款(1为接受)

BlackNWhite 发表于 2015-9-16 12:50

blueshell1949 发表于 2015-9-9 16:28
请问楼主,怎么样才可以反编译得到源码呀?新手求问。谢谢您

.net程序可以用DOTPEEK或.net reflector等工具实现,C++没有一个好的办法,逆向一般通过OD等调试工具实现

轻狂书生 发表于 2015-8-28 17:29

原创作品啊。。。。学习支持了

xiaogao66 发表于 2015-8-28 20:37

好东西,

720830 发表于 2015-8-29 00:49

看完了,期待发出来

海风爸爸 发表于 2015-8-29 09:30

太厉害了啊佩服的五体投地啊

BlackNWhite 发表于 2015-8-29 10:18

XhyEax 发表于 2015-8-28 16:52
然而网址还是没打码。。。。

楼主,经我测试,那个postdata里的很多参数都可以不带,进行注册 ...

哦哦,好的,感谢测试   (^_^)

BlackNWhite 发表于 2015-8-29 10:23

720830 发表于 2015-8-29 00:49
看完了,期待发出来

不能发,是违规的。
实现的思路和原理应该不难,照上面的自己实现一下就能用了

灬小数学 发表于 2015-8-29 14:53

犭王人曰女支 发表于 2015-8-29 16:42

学习了!!
页: [1] 2 3
查看完整版本: 对某校园网跨域软件的逆向分析和重实现