吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 27423|回复: 52
收起左侧

[PC样本分析] 盛大69棋牌游戏木马分析

  [复制链接]
零度x 发表于 2014-1-7 12:32
使用论坛附件上传样本压缩包时必须使用压缩密码保护,压缩密码:52pojie,否则会导致论坛被杀毒软件等误报,论坛有权随时删除相关附件和帖子!
病毒分析分区附件样本、网址谨慎下载点击,可能对计算机产生破坏,仅供安全人员在法律允许范围内研究,禁止非法用途!
禁止求非法渗透测试、非法网络攻击、获取隐私等违法内容,即使对方是非法内容,也应向警方求助!
本帖最后由 零度x 于 2014-1-16 11:42 编辑

盛大69棋牌游戏木马分析.rar (823.61 KB, 下载次数: 76)
首先我们先来看一下这个游戏的加载方式,这个游戏是用ADOBE的AIR技术开发的
1.bmp

可以看到,游戏安装完成后核心是这3个文件,其中DeskPokerLoad.exe是主程序,运行后会调用游戏目录下的69game\AdobeAIR\Versions\1.0\Adobe AIR.dll,这个DLL会加载DeskPokerLoader.swf这个文件,这个文件会加载DeskPokerLoader.swf这个SWF文件,这个SWF只是个加载器,我们来看下反编译代码
2.bmp
3.bmp 上面标记箭头那个就是加载完成的回调函数,我们跟进去看一下
4.bmp
可以看到,这里运用了一个AS3的第三方库hurlant 里的DES算法去解密密钥是 5.bmp ,官网在这里

这里解密完了的数据在_loc_2里面,我们可以自己写代码等它解密完后把它保存一下
这里我们使用FLASHDEVELOP,当然这个软件只是个IDE,你要自己去下SDK和FLASHC CS 版本无所谓,一定要建AIR工程,不然不能使用文件保存功能,这里是是完整的代码
[Actionscript3] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package
{
      import flash.display.Sprite;
      import com.hurlant.crypto.symmetric.*;
      import flash.events.*;
      import flash.net.*;
      import flash.utils.*;
      import flash.filesystem.File;
      import flash.filesystem.FileMode;
      import flash.filesystem.FileStream;
      /**
       *...
       *@author 004
       */
      public class Main extends Sprite
      {
           public static var swf_name:String ="DeskPoker.swf";
           private var key:String ="activetuts";
           private var urlload:URLLoader;
           //=============================写入函数
           public static function writeAppFile(fileName:String,datas:ByteArray):void{
             var file:File = newFile(File.applicationDirectory.resolvePath(fileName).nativePath);
             var fs:FileStream = new FileStream();
             fs.open(file,FileMode.WRITE);
             fs.position = 0;
             fs.writeBytes(datas);
             fs.close();
        }
           public function Main():void
           {
                 this.urlload = new URLLoader();
 
                 this.urlload.dataFormat =URLLoaderDataFormat.BINARY;
           this.urlload.addEventListener(Event.COMPLETE,this.loadLocalSWFComplete);
 
                 var _loc_1:* = newURLRequest(swf_name);
            _loc_1.cacheResponse = false;
            _loc_1.useCache = false;
            this.urlload.load(_loc_1);
 
           }
   //==========================加载完成回调
      
[Actionscript3] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
private functionloadLocalSWFComplete(event:Event) : void[/align]           {
              var _loc_2:* = this.urlload.data;
            var _loc_3:* = new ByteArray();
            _loc_3.writeUTF(this.key);
            var _loc_4:* = new DESKey(_loc_3);
            var _loc_5:* = _loc_2.length &~127;
            var _loc_6:* = 0;
            while (_loc_6 < _loc_5)
            {
 
                _loc_4.decrypt(_loc_2, _loc_6);
                _loc_6 = _loc_6 + 128;
            }
           this.urlload.removeEventListener(Event.COMPLETE, this.loadLocalSWFComplete);
            this.urlload.close();
 
                 writeAppFile("C:\\Decode.swf",_loc_2);
           }
      }
 
 
}
//=======================================
我们把DeskPoker.swf拷贝到和编译好的解码SWF下的BIN同一个目录,然后对这个函数下断点单步看看
6.bmp
可以看到这里循环文件的大小进行相对解密,然后我们就直接把解密后的主SWF抠出来了
7.bmp
//====================
讲完解密后我们在来看看这个程序的登录方式
8.bmp
和所有程序一样嘛,我们来找按钮事件可以看到舞台里有个这个和登录界面一样
9.bmp 我们记住这个loginform然后在代码里去找
10.bmp
然后我们对这个类名查找所有引用得到这个
11.bmp
12.bmp
然后我们再对this.lf查找引用得到这句,这个是给按钮增加一个单击事件,我们来到onLogin这个函数
13.bmp
我们略掉一些代码看核心的
14.bmp
15.bmp
这里可以看到,取回用户名和密码还有验证码之后广播了一个login_tocom_enter消息,我们跟到消息处理函数
16.bmp
17.bmp
18.bmp
可以看到这里调用HTTP发送了一个tc_ask_mibao,tc_ask_mibao定义为
19.bmp
我们对程序抓包看一下,这是第一个包
[C++] 纯文本查看 复制代码
1
POST/G69LoginAPI/wechat/getlogintcard.jsp HTTP/1.1..Referer:app:/DeskPokerLoader.swf/[[DYNAMIC]]/1..Accept: text/xml, application/xml,application/xhtml+xml, text/html;q=0.9, text/plain;q=0.8, text/css, image/png,image/jpeg, image/gif;q=0.8, application/x-shockwave-flash, video/mp4;q=0.9,flv-application/octet-stream;q=0.8, video/x-flv;q=0.7, audio/mp4,application/futuresplash, */*;q=0.5..x-flash-version: 11,1,102,58..Content-Type:application/x-www-form-urlencoded..Content-Length: 19..Accept-Encoding:gzip,deflate..User-Agent: Mozilla/5.0 (Windows; U; zh-CN) AppleWebKit/533.19.4(KHTML, like Gecko) AdobeAIR/3.1..Host: login.game69.com:8080..Connection:Keep-Alive....param=sfz009910&t=0
//============
然后它的HTTP发送类注册了一个回调函数用来接收返回的包
20.bmp
这里大概是根据返回包的xyh来进行操作
21.bmp
比如这里返回的是
{"res":1,"xyh":20006}
22.bmp
查找下getMibaoRe这个消息
23.bmp
这里res=1
24.bmp
25.bmp
xxx.bmp
这个就是第二个包
xxx2.bmp
好了,类似于这样,节省篇幅,我们直接跳到密码那里
26.bmp
可以看到发送密码的方式是这样,把密码机上jym这里是从服务器返回的一串数字,类似于这样"jym":"958184970",比如我密码是12345就是12345958184970,然后传给MD5进行加密后传到服务器,这里大概原理讲得差不多了,我们来看一下木马
27.bmp
这里比原版多了一个DLL文件,可以看到,这里的2个SWF文件都成一样了,其实就是木马作者把原版SWF解密出来后把原来的加载SWF替换成主SWF了,这里木马盗取密码的方式是这样的,修改原版的SWF文件,在发送密码+JYM组成的MD5的时候改成这样了

28.bmp 右边那个是木马的修改版,可以看到直接返回了,我们再来看看那个DLL文件
29.bmp


可以看到它HOOK了3个函数,我们先来看看send函数,首先判断方法
30.bmp
31.bmp
这里我们直接看登录页面
32.bmp 这里就提取数组了,我们看看原版的包是怎样的
[C++] 纯文本查看 复制代码
1
POST/G69LoginAPI/login.jsp HTTP/1.1..Referer:app:/DeskPokerLoader.swf/[[DYNAMIC]]/1..Accept: text/xml, application/xml,application/xhtml+xml, text/html;q=0.9, text/plain;q=0.8, text/css, image/png,image/jpeg, image/gif;q=0.8, application/x-shockwave-flash, video/mp4;q=0.9,flv-application/octet-stream;q=0.8, video/x-flv;q=0.7, audio/mp4,application/futuresplash, */*;q=0.5..x-flash-version: 11,1,102,58..Content-Type:application/x-www-form-urlencoded..Content-Length: 114..Accept-Encoding:gzip,deflate..User-Agent: Mozilla/5.0 (Windows; U; zh-CN) AppleWebKit/533.19.4(KHTML, like Gecko) AdobeAIR/3.1..Host: login.game69.com:8080..Connection:Keep-Alive..Cookie:JSESSIONID=7349A2008A40E3D2D3E41AF5CED014E1....type=1&pw=ce5d8df64486b34bfa0bb75ca16c429f&yzm=%E8%AF%B7%E8%BE%93%E5%85%A5%E9%AA%8C%E8%AF%81%E7%A0%81&un=sfz009910
但被木马修改版的就成这样了
[C++] 纯文本查看 复制代码
1
type=1&pw=12345958184970=%E8%AF%B7%E8%BE%93%E5%85%A5%E9%AA%8C%E8%AF%81%E7%A0%81&un=sfz009910
//=========
这里木马扣除密码后,再根据原版密码和那个JYM加密成MD5装到包里发送给服务器还会在本地保存一份
33.bmp
34.bmp
然后就会给服务器发消息了,调用这个函数
35.bmp
格式化是这样的
36.bmp
这样吧,我们动态调试一下,首先对HOOK的SEND下个断点,再对格式化这个函数下个断点,可以看到这种,这里那个扫描8T1L的好像是计算机名密码和用户是出来了,
37.bmp
再F9一下
38.bmp
可以看到多了一串32位的MD5,这串MD5是怎么来的呢,是它自己生成的
[C++] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
typedefstruct    {  
      ULONG i[2];  
      ULONG buf[4];  
      unsigned char in[64];  
      unsigned char digest[16];  
} MD5_CTX;
 
typedef void(CALLBACK* MD5Init_Tpye)(MD5_CTX* context);
typedef void(CALLBACK* MD5Update_Tpye)(MD5_CTX* context,              unsigned char* input,                       unsigned int inlen);
typedef void(CALLBACK* MD5Final_Tpye)(MD5_CTX* context);
int main(intargc, char* argv[])
{
      HINSTANCE hDLL =LoadLibrary("advapi32.dll");
      MD5Init_Tpye   MD5Init;
      MD5Update_Tpye MD5Update;
      MD5Final_Tpye  MD5Final;
 
      MD5Init =(MD5Init_Tpye)GetProcAddress(hDLL, "MD5Init");
      MD5Update =(MD5Update_Tpye)GetProcAddress(hDLL, "MD5Update");
      MD5Final =(MD5Final_Tpye)GetProcAddress(hDLL, "MD5Final");
 
 
      MD5_CTX md5_context;  
      MD5Init(&md5_context);  
      unsigned char src[100];
 
      unsigned length = strlen(argv[1]);
 
      memcpy(src, argv[1], length);
 
      MD5Update(&md5_context, src, length);
 
      MD5Final(&md5_context);
 
      char dest[100] = { 0 }; 
      char *p = dest;
 
      for(int i = 0; i < 16; ++i) 
      {  
           sprintf(p,"%02x",md5_context.digest);  
           p += 2;  
      }  
 
      cout << dest << endl;
      return 0;
}
//============
用的是这个方法,那么生成这串MD5的是什么东西呢,这里第一次其实是空的没啥用,要知道是干嘛用的我们还要首先说一下,棋牌游戏都有个绑定机器的功能,我们让它进入游戏后,看一下 39.bmp
有个绑定按钮,我们按一下可以看到马上就断下了
40.bmp
可以看到这个MD5变了,这究竟是为什么呢?给我捐款我就告诉你 - -,抱怨一下,好了,我们想要知道为什么肯定就要去找源码来看看,
41.bmp
期间步骤我就不说了,直接来到关键点,发送绑定消息后服务器会返回一个一个code什么什么,可以看到这里把返回的这个CODE保存了,
42.bmp
看一下登录的时候有个
43.bmp
这里的意思就是获取MAC加上什么东西然后加密成MD5发送,可是this.getmac()这个函数是个空函数,那么完全就依靠后来的readfile函数了,
44.bmp
等于读取的就是之前服务器返回的那串,这下知道木马为什么截取这个MD5了吧,
这里我们玩玩谢幕游戏,根据DLL里的什么OutputDebugStringA("yushaowoshimima");可以社工下,其实这些无聊可以不看了
45.bmp
查下它服务器的IP
46.bmp
然后我们扫描一下
47.bmp
但我这个是内网,具体成功没我也不知道没去试了,好了这个样本我就不上传,以防被别人拿去用。

点评

膜拜大神  发表于 2014-1-20 15:43

免费评分

参与人数 3热心值 +3 收起 理由
YHZX_2013 + 1 谢谢@Thanks!
b0y + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.
1.shui + 1 完全看不懂,支持+1

查看全部评分

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

小人物大智慧 发表于 2014-1-7 12:36
沙发 膜拜下楼主 好文章
战股神 发表于 2014-1-7 12:41
k623277335 发表于 2014-1-7 13:24
natdon 发表于 2014-1-7 15:26
虽然很详细 但是功力不够看不懂
dingmai1991 发表于 2014-1-20 15:35
支持 原创描写得很详细,学习了!
iqionghai 发表于 2014-1-20 15:39
很详细的教程,不写个专杀工具出来多可惜啊。。我也一直想知道分析木马是用什么软件载入分析的
红茶 发表于 2014-1-20 15:44
谢谢分享
UUU 发表于 2014-1-20 15:57
学习了,多谢分享
www52pojiecn 发表于 2014-1-20 17:07
谢谢,虽然看不懂,还是膜拜先
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2025-3-27 11:13

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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