Analysis of FG-IR-22-369 | Fortinet Blog
打开虚拟机,设置用户名和密码为admin:admin,以及设置网络为169.254.48.205
config system interface
edit port1
set mode static
set 169.254.48.205 255.255.0.0
end
execute ..
diagnose hardware lspci
于是去下载toolchain,下载musl的,编译出来的会比较小。
Socket的代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/wait.h>
#define DEST_PORT 7777//目标地址端口号
#define DEST_IP "169.254.48.206"/*目标地址IP,这里设为本机*/
#define MAX_DATA 100//接收到的数据最大程度
int main(){
int sockfd,new_fd;/*cocket句柄和接受到连接后的句柄 */
struct sockaddr_in dest_addr;/*目标地址信息*/
char buf[MAX_DATA];//储存接收数据
sockfd=socket(AF_INET,SOCK_STREAM,0);/*建立socket*/
if(sockfd==-1){
printf("socket failed:%d",errno);
}
//参数意义见上面服务器端
dest_addr.sin_family=AF_INET;
dest_addr.sin_port=htons(DEST_PORT);
dest_addr.sin_addr.s_addr=inet_addr(DEST_IP);
bzero(&(dest_addr.sin_zero),8);
if(connect(sockfd,(struct sockaddr*)&dest_addr,sizeof(struct sockaddr))==-1){//连接方法,传入句柄,目标地址和大小
printf("connect failed:%d",errno);//失败时可以打印errno
} else{
printf("connect success");
recv(sockfd,buf,MAX_DATA,0);//将接收数据打入buf,参数分别是句柄,储存处,最大长度,其他信息(设为0即可)。
printf("Received:%s",buf);
}
close(sockfd);//关闭socket
return 0;
}
}
Socket的服务端就是listen即可
import argparse
import socket
import sys
def main():
parser = argparse.ArgumentParser(description='Python netcat')
parser.add_argument('-l', '--listen', action='store_true', help='listen mode')
parser.add_argument('host', nargs='?', default='localhost', help='target host')
parser.add_argument('port', type=int, help='target port')
args = parser.parse_args()
if args.listen:
# listen mode
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((args.host, args.port))
server_socket.listen(1)
print(f'Listening on {args.host}:{args.port}')
conn, addr = server_socket.accept()
print(f'Connected by {addr[0]}:{addr[1]}')
while True:
data = conn.recv(1024)
if not data:
break
sys.stdout.write(data.decode())
sys.stdout.flush()
try:
line = input()
except EOFError:
break
conn.sendall(line.encode())
else:
# connect mode
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((args.host, args.port))
while True:
try:
line = input()
except EOFError:
break
client_socket.sendall(line.encode())
data = client_socket.recv(1024)
if not data:
break
sys.stdout.write(data.decode())
sys.stdout.flush()
if __name__ == '__main__':
main()
实现的TFTP如下:
import os
import socket
import datetime
import struct
# coding=utf-8
# -*- coding: utf-8 -*-
class TFTPServer:
_DOWNLOAD = 1
_UPLOAD = 2
_DATA = 3
_ACK = 4
_ERROR = 5
_oACK = 6
FILE_PATH = os.path.join(os.path.abspath('case'), 'video')
LOCAL_FILE_PATH = os.path.join(FILE_PATH, 'local')
def __init__(self, address: str, file_root=FILE_PATH):
self.address = address
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server_socket.bind((address,69))
self.file_root = file_root
if not os.path.exists(self.file_root):
os.makedirs(self.file_root)
self.receive_data = None
self.client_address = None
self.operator_code = None
self.progress = 0
self.run_result = None
self.upload_status = None
self.upload_run_result = None
def run(self):
while True:
print(u"wait client ")
self.listen()
print(u"operator_code", self.operator_code)
if self.operator_code == self._DOWNLOAD:
self.progress = 0
self.run_result = self.download()
elif self.operator_code == self._UPLOAD:
self.upload_status = None
self.upload_run_result = self.upload()
def listen(self):
self.receive_data, self.client_address = self.server_socket.recvfrom(1024)
unpack_data = self.__unpack_data(self.receive_data, 2)
print("listen data", unpack_data)
self.operator_code = unpack_data.get('operator_code')
CURRENT = datetime.datetime.now().strftime('%y-%m-%d %H:%M')
print(CURRENT, "received data:", self.receive_data, "client address:", self.client_address,
'operator_code:', self.operator_code)
# 客户端请求下载
def download(self):
self.run_result = None
self.progress = 0
down_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
print("ask for download")
# 打开需要下载的文件
download_file = None
# 下载文件的块编码
send_frame_no = 1
try:
unpack_data = self.__unpack_data(self.receive_data, 2)
if len(unpack_data.get('data', [])) == 0:
return
#file_path = os.path.join(self.file_root, unpack_data.get('data', [])[0])
file_path = os.path.join(self.file_root,'a.out')
current_send_size = 0
open_result, download_file, file_size = self.__open_file(down_socket, file_path)
if not open_result:
return False
# 发送OACK包,告诉客户端文件的大小,客户端可以显示进度
o_ack_data = struct.pack("!H5sb%dsb" % len(str(file_size)), 6, b'tsize', 0, str(file_size).encode(), 0)
down_socket.sendto(o_ack_data, self.client_address)
# 传输文件
while True:
res_file_data = download_file.read(512)
if send_frame_no > 65535:
send_frame_no = 1
# 打包
frame_data = struct.pack("!HH", 3, send_frame_no) + res_file_data
current_send_size += len(res_file_data)
self.progress = round((current_send_size / file_size) * 100, 1)
if int(self.progress) % 10 == 0:
print("==send:block num", send_frame_no, 'send address', self.client_address, 'progress:', self.progress, '%=')
self.__re_send_file(down_socket, frame_data, send_frame_no)
if len(res_file_data) < 512:
print("file successful transmit!")
download_file.close()
download_file = None
return True
send_frame_no += 1
except Exception as download_error:
print("TFTP transmit failed", download_error.__str__())
return False
finally:
print("closs file")
down_socket.close()
# 关闭文件
if download_file is not None:
download_file.close()
def __open_file(self, down_socket, file_path):
try:
file_size = os.path.getsize(file_path)
download_file = open(file_path, "rb")
return True, download_file, file_size
except Exception as file_error:
# 打开文件错误,向客户端发送错误的信息
print("file not exist" % file_path, file_error.__str__())
# 操作码 + 差错码 + 差错信息 + 块编号
error_info = struct.pack("!HHHb", 5, 5, 5, 1)
down_socket.sendto(error_info, self.client_address)
return False, None, 0
def __re_send_file(self, down_socket, frame_data, send_frame_no):
for i in range(0, 3):
down_socket.sendto(frame_data, self.client_address)
# 等待client响应
self.receive_data, self.client_address = down_socket.recvfrom(1024)
receive_unpack = self.__unpack_data(self.receive_data, 4)
# 收到确认码,不在重复发送, 确认的块编号和发送的一样
if receive_unpack.get('operator_code') == self._ACK and (
receive_unpack.get('frame_no') == send_frame_no):
break
elif i == 3:
print("link error")
error_info = struct.pack("!HHHb", 5, 5, 5, 0)
down_socket.sendto(error_info, self.client_address)
# 客户端请求上传
def upload(self):
try:
self.upload_run_result = None
# 新建随机端口
upload_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
ack = struct.pack("!HH", self._ACK, 0)
upload_socket.sendto(ack, self.client_address)
operation_unpack_data = self.__unpack_data(self.receive_data, 2)
self.upload_status = 1
if len(operation_unpack_data.get('data', [])) == 0:
print("TFTP:not received")
return False
upload_file_path = os.path.join(self.file_root, operation_unpack_data.get('data', [])[0])
print("upload path, upload_file_path")
return self.__save_upload_data(upload_socket, upload_file_path)
except Exception as upload_error:
print("TFTP:FAILED_DEPENDENCY", upload_error.__str__())
print("failed transmit", upload_error.__str__())
return False
def __save_upload_data(self, upload_socket, upload_file_path):
frame_no = 1
open_file = None
while True:
self.upload_status = 2
receive_data, receive_address = upload_socket.recvfrom(1024)
# 数据帧
unpack_data = self.__unpack_data(receive_data, 4)
if unpack_data.get('operator_code') == self._DATA and unpack_data.get('frame_no') == frame_no:
# 打开文件
if unpack_data.get('frame_no') == 1:
open_file = open(upload_file_path, "ab")
if open_file is not None:
open_file.write(receive_data[4:])
# 响应
ack = struct.pack("!HH", self._ACK, unpack_data.get('frame_no'))
upload_socket.sendto(ack, receive_address)
if len(receive_data) < 516:
open_file.close()
self.upload_status = 3
print("TFTP: finished")
return True
frame_no += 1
elif unpack_data.get('operator_code') == self._ERROR:
print("TFTP: failed 233" + unpack_data.get('data'))
return False
@staticmethod
def __unpack_data(receive_data, code_num: int = 2):
msg = {'operator_code': -1, 'frame_no': -1, 'data': []}
if code_num == 2:
msg['operator_code'] = struct.unpack("!H", receive_data[:2])[0]
else:
operator_code, frame_no = struct.unpack("!HH", receive_data[:4])
msg['operator_code'] = operator_code
msg['frame_no'] = frame_no
if len(receive_data) > code_num and msg.get('operator_code') != 3:
unpack_data = receive_data[code_num:].decode('UTF-8', 'ignore').strip().split(b'\x00'.decode())
unpack_data = [data for data in unpack_data if data != '']
msg['data'] = unpack_data
return msg
def kill_process(self, port):
try:
with os.popen("netstat -nao|findstr " + str(port)) as res:
res = res.read().split('\n')
pid = ''
for line in res:
if line.find(':%s ' % port) == -1:
continue
temp = [i for i in line.split(' ') if self._is_number(i)]
if len(temp) == 1:
pid = temp[0]
break
print("kill:pid:", pid)
if pid != '':
os.popen('taskkill /pid ' + str(pid) + ' /F')
except Exception as error:
print("fail close port" + error.__str__())
from threading import Thread
if __name__ == "__main__":
file_path = 'C:\\Users\\zzq\\Desktop\\test'
address = '169.254.48.206'
# 开始监听69串口,启用tftp服务
t = Thread(target=TFTPServer(address,file_path).run)
t.start()
t.join(1)