https://www.ichunqiu.com/battalion?t=1&r=70899
+ + + + + + + + + + +
关于可信度量赛题的设计与思考
作者:北京工业大学国家等级保护2.0与可信计算3.0攻关示范基地 胡俊
1. 可信度量赛题的设计
2.解题思路
if (Memcmp(external_data_store, quote_report - > nonce, DIGEST_SIZE) != 0)
// 通过对比回传随机数,确定报告是否为重放报告
{
Strcpy(solve_result, "error");
} else if (Memcmp(quote_report - > pcrComp.pcrValue, empty_digest, DIGEST_SIZE) == 0) {
//当Pcr值为全零时,设策略为空
Strcpy(solve_result, "null");
} else {
//示例代码:遍历所有策略摘要,顺便对策略数目进行计数
//因为策略摘要是以哈希表方式存放,因此遍历次序与存入次序无关
policy_digest = memdb_get_first_record(TYPE_PAIR(GENERAL_RETURN, UUID));
while (policy_digest != NULL) {
record_count++;
printf("policy name : %s value :", policy_digest - > name);
print_bin_data(policy_digest - > return_value, 32, 16);
policy_digest = memdb_get_next_record(TYPE_PAIR(GENERAL_RETURN, UUID));
}
BYTE * uuid_list;
char * name_buf;
// 分配空间准备按顺序存储策略摘要值
uuid_list = Talloc0(DIGEST_SIZE * record_count);
i = 0;
j = 0;
// 按照策略写入顺序排序存储策略摘要值
policy_digest = memdb_get_first_record(TYPE_PAIR(GENERAL_RETURN, UUID));
while (policy_digest != NULL) {
for (j = 0; j < record_count; j++) {
if (policy_seq[j] == NULL)
break;
if (Strcmp(policy_seq[j], policy_digest - > name) == 0) {
Memcpy(uuid_list + j * DIGEST_SIZE, policy_digest - > return_value, DIGEST_SIZE);
break;
}
}
policy_digest = memdb_get_next_record(TYPE_PAIR(GENERAL_RETURN, UUID));
i++;
}
int choice = 1;
choice <<= record_count;
BYTE pcr_emu[DIGEST_SIZE];
BYTE pcr_buf[DIGEST_SIZE * 2];
// 遍历对照所有策略,找到匹配的策略组合
for (i = 1; i <= choice; i++) {
Memset(pcr_buf, 0, DIGEST_SIZE);
int temp = i;
for (j = 0; j < record_count; j++) {
if (temp % 2) {
Memcpy(pcr_buf + DIGEST_SIZE, uuid_list + j * DIGEST_SIZE, DIGEST_SIZE);
calculate_context_sm3(pcr_buf, DIGEST_SIZE * 2, pcr_emu);
Memcpy(pcr_buf, pcr_emu, DIGEST_SIZE);
}
temp >>= 1;
}
if (Memcmp(pcr_emu, quote_report - > pcrComp.pcrValue, DIGEST_SIZE) == 0) {
int k;
temp = i;
for (k = 0; k < record_count; k++) {
if (temp % 2) {
if (solve_result[0] == 0)
Strcpy(solve_result, policy_seq[k]);
else {
Strcat(solve_result, "|");
Strcat(solve_result, policy_seq[k]);
}
}
temp >>= 1;
}
break;
}
}
printf("solve result: %sn", solve_result);
}
3.可信度量赛题的思考
-
初赛题目众多,选择熟悉的题目求解是更稳妥的选择。 -
感觉题目不容易抓住重点,读懂题目说明、读懂相关代码还是有相当难度的。 -
出题者以为PCR寄存器写入知识是常识或者很容易查到,实际并非如此。 -
队伍主要训练的是传统CTF类题目,缺少解答本题目的相关技能。 -
在对可信计算知识了解甚少的情况下,难以进行思维跳跃以找到解题思路。
一血队伍解法
作者:Jemmy@NEX
-
检查 quote_report
中的nonce
值是否是我们服务器刚才生成的,不符合时直接返回”error”。 -
确认 quote_report->nonce
值有效之后,检查quote_report
中的pcrValue
是否有启用的安全策略,当pcrValue为全0的时候没有任何启用的策略返回”null”,其他值时需要解析启用安全的策略。 -
在 pcrValue
非全0时按照“科研-生产-测试-公开”的顺序解析启用的安全策略,有多个策略时两个策略间用”|”分隔。
0. 编写代码的一些准备工作
player.sh
就能够获得flag。题目中涉及大量自定义数据结构,不建议通过查询头文件来了解其结构,建议测试运行后,观察instance/crypt_hub/message.log,既可以追踪整个过程,也可以看到相关数据结构的内容。
message.log
的方式能够更容易地了解到数据结构的内容。1. 检查nonce值
key_manage.c
的这个位置,是生成并返回nonce
随机值的地方。nonce
随机值保存在了external_data_store
变量中。我们只需要在quote_report
中的nonce
值与external_data_store
变量中的预期nonce值进行比较即可。if (Memcmp(external_data_store, quote_report->nonce, DIGEST_SIZE))
{
/* quote_report中的nonce 与 external_data_store 中的预期值不符 */
printf("!!!!!!!!!!!!! Wrong nonce !!!!!!!!!!!!!!n");
Strcpy(solve_result, "error");
}
2. 检查启用的安全策略是否为空
pcrValue
应该是全0的。在key_manage.c
中也特意帮我们定义并清空了一个叫empty_digest
的变量,我们只需要用Memcmp
来比较pcrValue
与empty_digest
。/* 紧接着上一段代码 */
else if (Memcmp(quote_report->pcrComp.pcrValue, empty_digest, DIGEST_SIZE) == 0)
{
/* pcrValue没有被扩展过,表示启用的策略为空 */
printf("!!!!!!!!!!!!! Empty policy !!!!!!!!!!!!!!n");
Strcpy(solve_result, "null");
}
3. 解析启用的安全策略
newPcrValue = HASH(oldPcrValue || digestValue)
,也就是说我们将原来的PCR值oldPcrValue
与想要扩展的摘要值digestValue
拼接起来,然后再进行一次哈希运算,将结果写入PCR寄存器中。在国产的TCM芯片中,这个HASH操作是SM3算法。quote_report
中的pcrValue
就是这样读取出来的。2^4 = 16
种可能性。我们可以通过枚举的方式来计算这16种情况下的PCR值,然后与quote_report
中的pcrValue
进行比较,找到启用的安全策略。digestValue
,这一部分代码已经在key_manage.c
中给出了,我们只需对其做一点点修改,将这些摘要值保存在一个数组里。/* 紧接着上一段代码 */
else
{
BYTE ServerValues[4][DIGEST_SIZE];
// find the choiced policies
// show all the policies
policy_digest = memdb_get_first_record(TYPE_PAIR(GENERAL_RETURN, UUID));
while (policy_digest != NULL)
{
record_count++;
printf("policy name : %s value :", policy_digest->name);
namelen_sum += Strlen(policy_digest->name) + 1;
print_bin_data(policy_digest->return_value, 32, 16);
if (!Strcmp(policy_digest->name, "research"))
Memcpy(ServerValues[0], policy_digest->return_value, DIGEST_SIZE);
else if (!Strcmp(policy_digest->name, "product"))
Memcpy(ServerValues[1], policy_digest->return_value, DIGEST_SIZE);
else if (!Strcmp(policy_digest->name, "test"))
Memcpy(ServerValues[2], policy_digest->return_value, DIGEST_SIZE);
else if (!Strcmp(policy_digest->name, "public"))
Memcpy(ServerValues[3], policy_digest->return_value, DIGEST_SIZE);
policy_digest = memdb_get_next_record(TYPE_PAIR(GENERAL_RETURN, UUID));
}
/* 下一段代码将要补充在这里 */
/* ...... */
}
solve_result
来存储oldPcrValue || digestValue
的拼接结果,哈希之后的newPcrValue
存储到了empty_digest
中。calculate_context_sm3
的函数,这是通过在所有代码文件中搜索”sm3″找到的,根据其他地方的用法可以猜出函数定义是calculate_context_sm3(BYTE const* bufInput, int bufLen, BYTE* outHashBuf)
,这个函数的作用是将bufInput
中的bufLen
个字节进行哈希运算,结果存入outHashBuf
中。 /* 填充在上一段代码中标注的位置 */
int policyNum;
for (policyNum = 0; policyNum < 16; ++policyNum)
{
/* 清空pcr缓存数组 */
Memset(solve_result, 0, DIGEST_SIZE * 2);
int bit;
for (bit = 0; bit < 4; ++bit)
{
if (policyNum & (1 << bit))
{
/* 将digestValue拼接到当前PCR值的后面(solve_result偏移DIGEST_SIZE的位置) */
Memcpy(solve_result + DIGEST_SIZE, ServerValues[bit], DIGEST_SIZE);
/* 计算新的PCR值,存储到empty_digest中 */
calculate_context_sm3(solve_result, sizeof(solve_result), empty_digest);
/* 将新的PCR值再复制回solve_result里 */
Memcpy(solve_result, empty_digest, DIGEST_SIZE);
}
}
/* 下一段代码将要补充在这里 */
/* ...... */
}
/* 与所有可能的策略组合都不匹配,不应该出现这一情况 */
Strcpy(solve_result, "unexpected");
quote_report
中的pcrValue
是否相等了。相等的话就找到了启用的安全策略,将这些策略拼接成一个字符串,存入solve_result
跳出循环即可。 /* 填充在上一段代码中标注的位置 */
if (Memcmp(quote_report->pcrComp.pcrValue, solve_result, DIGEST_SIZE) == 0)
{
printf("!!!!!!!!!!!!! Found policy %d !!!!!!!!!!!!!!n", policyNum);
/* 清空solve_result变量,来存储结果字符串 */
Strcpy(solve_result, "");
/* 表示是否需要拼接'|'符号,第一个解析出的策略不需要,后续需要拼接 */
int append = 0;
int bit;
for (bit = 0; bit < 4; ++bit)
{
if (policyNum & (1 << bit))
{
/* 当这一安全策略被启用时 */
if (append)
Strcat(solve_result, "|"); /* 根据append判断是否需要拼接'|' */
/* 拼接安全策略字符串 */
Strcat(solve_result, policy_seq[bit]);
append = 1;
}
}
goto finish;
}
// check program begin
int record_count = 0;
int namelen_sum = 0;
BYTE empty_digest[DIGEST_SIZE];
char solve_result[DIGEST_SIZE * 2];
RECORD(GENERAL_RETURN, UUID) * policy_digest;
Memset(empty_digest, 0, DIGEST_SIZE);
Memset(solve_result, 0, DIGEST_SIZE * 2);
if (Memcmp(external_data_store, quote_report->nonce, DIGEST_SIZE))
{
printf("!!!!!!!!!!!!! Wrong nonce !!!!!!!!!!!!!!n");
Strcpy(solve_result, "error");
}
else if (Memcmp(quote_report->pcrComp.pcrValue, empty_digest, DIGEST_SIZE) == 0)
{
printf("!!!!!!!!!!!!! Empty policy !!!!!!!!!!!!!!n");
Strcpy(solve_result, "null");
}
else
{
BYTE ServerValues[4][DIGEST_SIZE];
// find the choiced policies
// show all the policies
policy_digest = memdb_get_first_record(TYPE_PAIR(GENERAL_RETURN, UUID));
while (policy_digest != NULL)
{
record_count++;
printf("policy name : %s value :", policy_digest->name);
namelen_sum += Strlen(policy_digest->name) + 1;
print_bin_data(policy_digest->return_value, 32, 16);
if (!Strcmp(policy_digest->name, "research"))
Memcpy(ServerValues[0], policy_digest->return_value, DIGEST_SIZE);
else if (!Strcmp(policy_digest->name, "product"))
Memcpy(ServerValues[1], policy_digest->return_value, DIGEST_SIZE);
else if (!Strcmp(policy_digest->name, "test"))
Memcpy(ServerValues[2], policy_digest->return_value, DIGEST_SIZE);
else if (!Strcmp(policy_digest->name, "public"))
Memcpy(ServerValues[3], policy_digest->return_value, DIGEST_SIZE);
policy_digest = memdb_get_next_record(TYPE_PAIR(GENERAL_RETURN, UUID));
}
int policyNum;
for (policyNum = 0; policyNum < 16; ++policyNum)
{
Memset(solve_result, 0, DIGEST_SIZE * 2);
int bit;
for (bit = 0; bit < 4; ++bit)
{
if (policyNum & (1 << bit))
{
Memcpy(solve_result + DIGEST_SIZE, ServerValues[bit], DIGEST_SIZE);
calculate_context_sm3(solve_result, sizeof(solve_result), empty_digest);
Memcpy(solve_result, empty_digest, DIGEST_SIZE);
}
}
if (Memcmp(quote_report->pcrComp.pcrValue, solve_result, DIGEST_SIZE) == 0)
{
printf("!!!!!!!!!!!!! Found policy %d !!!!!!!!!!!!!!n", policyNum);
Strcpy(solve_result, "");
int append = 0;
int bit;
for (bit = 0; bit < 4; ++bit)
{
if (policyNum & (1 << bit))
{
if (append)
Strcat(solve_result, "|");
Strcat(solve_result, policy_seq[bit]);
append = 1;
}
}
goto finish;
}
}
/* Not Found */
Strcpy(solve_result, "unexpected");
}
finish:
printf("solve result: %sn", solve_result);
// check program end
src
文件夹后,运行make
重新编译,然后运行player.sh
,就能够获得flag了。二血队伍解法
作者:zeroc@F1sh
crypt_hub
模块中的 key_manage
的代码来实现对重放攻击的检测与报告内容的解析。执行流程
tcm_quote.sh
并且通过生成的 instance/crypt_hub/message.log
来了解其执行流程:-
首先是启动整个可信计算的流程:
{
"HEAD":{
"tag":"MESG","version":65537,"sender_uuid":"","receiver_uuid":"","route
":"","flow":"FINISH","state":"MATCH","flag":"NULL","ljump":1,"rjump":1,"record_t
ype":"MESSAGE","record_subtype":"CONN_ACKI","record_num":1,"record_size":151,"ex
pand_num":0,"expand_size":0,"msg_uuid":"a71819163c8f8caedf94cc09a94684488e476593
9a5a77533b54955db9032b40"
},
"RECORD":[
{
"uuid":"b16eb1b46c2d00f92a6fb8f3c7c304127fdf4da7db51f195acb18b9e432e71c6","clie
nt_name":"server","client_proc":"server","client_addr":"unknown addr","server_uu
id":"b16eb1b46c2d00f92a6fb8f3c7c304127fdf4da7db51f195acb18b9e432e71c6","server_n
ame":"crypt_hub","service":"trust_server","server_addr":"","flags":0,"nonce":""
}
],
"EXPAND" :[]
}
-
接着进行第一次 pcrquote
,由key_manage
生成随机的 nonce 用于防范重放攻击并返回给 user:
{
"HEAD":{
"tag":"MESG","version":65537,"sender_uuid":"7862491328c47d0648b97c5abd1
5a93442bd1c974b77607314da3c0156bac929","receiver_uuid":"key_manage","route":"quo
te_nonce","flow":"QUERY","state":"MATCH","flag":"LOCAL","ljump":1,"rjump":2,"rec
ord_type":"GENERAL_RETURN","record_subtype":"STRING","record_num":1,"record_size
":12,"expand_num":0,"expand_size":0,"msg_uuid":"de44c053015ab9b5e531cea46bfa6e96
c8b0d0b19c890e0ff945005b47da6e1c"
},
"RECORD":[
{
"name":"pcrquote","return_value":"14"
}
],
"EXPAND" :[]
}
************************************************************
{
"HEAD":{
"tag":"MESG","version":65537,"sender_uuid":"key_manage","receiver_uuid"
:"7862491328c47d0648b97c5abd15a93442bd1c974b77607314da3c0156bac929","route":"quo
te_nonce","flow":"QUERY","state":"RESPONSE","flag":"NULL","ljump":2,"rjump":2,"r
ecord_type":"GENERAL_RETURN","record_subtype":"STRING","record_num":1,"record_si
ze":12,"expand_num":1,"expand_size":0,"msg_uuid":"de44c053015ab9b5e531cea46bfa6e
96c8b0d0b19c890e0ff945005b47da6e1c"
},
"RECORD":[
{
"name":"pcrquote","return_value":"14"
}
],
"EXPAND" :[
{
"data_size":0,"type":"GENERAL_RETURN","subtype":"UUID","expand":
{
"name":"pcrquote","return_value":"fded59495cb4a8c1ecae6d8f801fca1f541dffc36cf1e
d10281bf3323d2722fa"
}
}
]
}
key_manage.c
中对应的代码段为:// check if there exists random data
ret = message_remove_expand(recv_msg,TYPE_PAIR(GENERAL_RETURN,UUID),&msg_expand);
if(msg_expand == NULL)
{
// generate external random data
RECORD(GENERAL_RETURN,UUID) * external_data;
external_data=Talloc0(sizeof(*external_data));
external_data->name=dup_str("pcrquote",0);
RAND_bytes(external_data->return_value,DIGEST_SIZE);
Memcpy(external_data_store,external_data->return_value,DIGEST_SIZE);
ret = message_add_expand_data(recv_msg,TYPE_PAIR(GENERAL_RETURN,UUID),external_data);
ret=ex_module_sendmsg(sub_proc,recv_msg);
}
-
然后 key_event
在报告中添加用户以及节点信息,由crypt_user
将 pcr 的值读出后写入报告模板,发送给key_manage
,key_manage
需要将报告转发给quote_report
:
{
"HEAD":{
"tag":"MESG","version":65537,"sender_uuid":"7862491328c47d0648b97c5abd1
5a93442bd1c974b77607314da3c0156bac929","receiver_uuid":"key_manage","route":"quo
te_verify","flow":"QUERY","state":"MATCH","flag":"LOCAL","ljump":1,"rjump":2,"re
cord_type":"GENERAL_RETURN","record_subtype":"STRING","record_num":1,"record_siz
e":12,"expand_num":2,"expand_size":439,"msg_uuid":"533de83d72e1ee88792152dfbfbf1
d1026f00167ba4bbd260e86f57c16de396e"
},
"RECORD":[
{
"name":"pcrquote","return_value":"14"
}
],
"EXPAND" :[
{
"data_size":0,"type":"MESSAGE","subtype":"INSTANCE_INFO","expand":
{
"proc_name":"term","node_uuid":"0fc56bb95fc2a0e6685fec12f31ea1cc03d470fa819f890
38822b9741741d8b2","user_name":"zhao"
}
},
{
"data_size":0,"type":"TCM_PIK_DESC","subtype":"PCRQUOTE","expand":
{
"userinfo":
{
"username":"zhao","user_role":"","node_uuid":"0fc56bb95fc2a0e6685fec12f31ea1cc0
3d470fa819f89038822b9741741d8b2","node_name":"","expand_digest":"","describe":"q
uote_report test"
},
"pcrComp":
{
"select":
{
"sizeOfSelect":0,"pcrSelect":"AEAA"
},
"valueSize":32,"pcrValue":"Pg0UXi2+FrqjK47s7+0C50WClHt15b27QjyxccClMz0"
},
"nonce":"fded59495cb4a8c1ecae6d8f801fca1f541dffc36cf1ed10281bf3323d2722fa","sign
Len":64,"signData":"drc3tcDRf33OKS/wKZbBGjP8cKuxIFGixmv+g0mRJAGUtGfYRxcYKyjxnIRt
yx4BOdTdWUEblhUlLjOtHjoN0w"
}
}
]
}
// key_manage 向 quote_report 转发信息
{
"HEAD":{
"tag":"MESG","version":65537,"sender_uuid":"key_manage","receiver_uuid"
:"quote_report","route":"quote_verify","flow":"QUERY","state":"MATCH","flag":"LO
CAL","ljump":2,"rjump":2,"record_type":"GENERAL_RETURN","record_subtype":"STRING
","record_num":1,"record_size":12,"expand_num":2,"expand_size":439,"msg_uuid":"5
33de83d72e1ee88792152dfbfbf1d1026f00167ba4bbd260e86f57c16de396e"
},
"RECORD":[
{
"name":"pcrquote","return_value":"14"
}
],
"EXPAND" :[
{
"data_size":0,"type":"MESSAGE","subtype":"INSTANCE_INFO","expand":
{
"proc_name":"term","node_uuid":"0fc56bb95fc2a0e6685fec12f31ea1cc03d470fa819f890
38822b9741741d8b2","user_name":"zhao"
}
},
{
"data_size":0,"type":"TCM_PIK_DESC","subtype":"PCRQUOTE","expand":
{
"userinfo":
{
"username":"zhao","user_role":"","node_uuid":"0fc56bb95fc2a0e6685fec12f31ea1cc0
3d470fa819f89038822b9741741d8b2","node_name":"","expand_digest":"","describe":"q
uote_report test"
},
"pcrComp":
{
"select":
{
"sizeOfSelect":0,"pcrSelect":"AEAA"
},
"valueSize":32,"pcrValue":"Pg0UXi2+FrqjK47s7+0C50WClHt15b27QjyxccClMz0"
},
"nonce":"fded59495cb4a8c1ecae6d8f801fca1f541dffc36cf1ed10281bf3323d2722fa","sign
Len":64,"signData":"drc3tcDRf33OKS/wKZbBGjP8cKuxIFGixmv+g0mRJAGUtGfYRxcYKyjxnIRt
yx4BOdTdWUEblhUlLjOtHjoN0w"
}
}
]
}
pcrValue
是使用 Base64 编码后的数据。key_manage.c
中对应的代码为:// prepare to verify quote report
printf("server: prepare to verify quote report!n");
RECORD(TCM_PIK_DESC,PCRQUOTE) * quote_report;
quote_report=msg_expand->expand;
DB_RECORD * db_record;
db_record = memdb_store(quote_report,TYPE_PAIR(TCM_PIK_DESC,PCRQUOTE),NULL);
if(db_record == NULL)
{
printf("server: store quote report failed!n");
}
print_bin_data(db_record->head.uuid,32,16);
ret=ex_module_sendmsg(sub_proc,recv_msg);
-
由于 quote_report
仅通过用户的密钥来验证消息的完整性,并不具备可信验证的功能,因此在quote_report
向key_manage
返回验证结果后,需要key_manage
对重放攻击进行检测、对可信报告进行解析并将结果返回给 user:
// quote_report 验证消息完整性后返回给 key_manage 的信息,result=0说明验证成功
{
"HEAD":{
"tag":"MESG","version":65537,"sender_uuid":"quote_report","receiver_uui
d":"key_manage","route":"quote_verify","flow":"QUERY","state":"MATCH","flag":"LO
CAL","ljump":3,"rjump":2,"record_type":"GENERAL_RETURN","record_subtype":"STRING
","record_num":1,"record_size":12,"expand_num":2,"expand_size":439,"msg_uuid":"5
33de83d72e1ee88792152dfbfbf1d1026f00167ba4bbd260e86f57c16de396e"
},
"RECORD":[
{
"name":"pcrquote","return_value":"14"
}
],
"EXPAND" :[
{
"data_size":0,"type":"MESSAGE","subtype":"INSTANCE_INFO","expand":
{
"proc_name":"term","node_uuid":"0fc56bb95fc2a0e6685fec12f31ea1cc03d470fa819f890
38822b9741741d8b2","user_name":"zhao"
}
},
{
"data_size":0,"type":"TCM_KEY_DESC","subtype":"VERIFY_DESC","expand":
{
"result":0,"object_uuid":"8267080f87fc66a093200ca17c4ca06cec4327d1dafcab861955f
d47c74cf259","verifykey_uuid":""
}
}
]
}
{
"HEAD":{
"tag":"MESG","version":65537,"sender_uuid":"key_manage","receiver_uuid"
:"7862491328c47d0648b97c5abd15a93442bd1c974b77607314da3c0156bac929","route":"quo
te_verify","flow":"QUERY","state":"RESPONSE","flag":"NULL","ljump":4,"rjump":2,"
record_type":"GENERAL_RETURN","record_subtype":"STRING","record_num":1,"record_s
ize":12,"expand_num":3,"expand_size":439,"msg_uuid":"533de83d72e1ee88792152dfbfb
f1d1026f00167ba4bbd260e86f57c16de396e"
},
"RECORD":[
{
"name":"pcrquote","return_value":"14"
}
],
"EXPAND" :[
{
"data_size":0,"type":"MESSAGE","subtype":"INSTANCE_INFO","expand":
{
"proc_name":"term","node_uuid":"0fc56bb95fc2a0e6685fec12f31ea1cc03d470fa819f890
38822b9741741d8b2","user_name":"zhao"
}
},
{
"data_size":0,"type":"TCM_KEY_DESC","subtype":"VERIFY_DESC","expand":
{
"result":0,"object_uuid":"8267080f87fc66a093200ca17c4ca06cec4327d1dafcab861955f
d47c74cf259","verifykey_uuid":""
}
},
{
"data_size":0,"type":"GENERAL_RETURN","subtype":"STRING","expand":
{
"name":"policy_choice","return_value":""
}
}
]
}
return_value
中写入解析结果。解题
key_manage.c
的一些对 recv_msg
的 TYPE_PAIR
类型的判断即可弄明白执行流程,那么这里我们需要做的工作有两个:-
判断是否存在重放攻击; -
不存在重放攻击的情况下,对 pcrValue
进行解析。
nonce
来实现,这里通过校验 key_manage
所生成的 nonce 与所接收到的 nonce 是否一致来进行判断,其中第一个 nonce 可以通过以下代码获取:RECORD(TCM_PIK_DESC,PCRQUOTE) * quote_report;
DB_RECORD * db_record;
db_record = memdb_find(verify_desc->object_uuid,TYPE_PAIR(TCM_PIK_DESC,PCRQUOTE));
if(db_record==NULL)
return -EINVAL;
printf("server: get verified report, verify result is %d!n",verify_desc->result);
quote_report = db_record->record;
char recv_nonce[32];
recv_nocne=quote_report->nonce
// general quote_report from (TCM_PIK_DESC,QUOTE_REPORT)
{
RECORD(MESSAGE,INSTANCE_INFO) * instance_info;
RECORD(TCM_PIK_DESC,PCRQUOTE) * quote_report;
// get quote nonce value
printf("key_manage: enter quote report get process!n");
RECORD(GENERAL_RETURN,UUID) * external_data = msg_expand->expand;
db_record = memdb_find_first(TYPE_PAIR(TCM_PIK_DESC,PCRQUOTE),"nonce",external_data->return_value);
FILE *file=fopen("/home/player/tcmenv_question/src/test.txt","w");
int k=0;
for(k=0;k<32;k++){
fprintf(file,"%d ",external_data->return_value[k]);
}
fclose(file);
if(db_record == NULL)
{
printf("key_manage: can't find quote report!n");
return -EINVAL;
}
quote_report = db_record->record;
if(quote_report == NULL)
return -EINVAL;
ret = message_add_expand_data(recv_msg,TYPE_PAIR(TCM_PIK_DESC,PCRQUOTE),quote_report);
ret=ex_module_sendmsg(sub_proc,recv_msg);
return ret;
}
pcrValue
的解析,pcrValue
的生成原理如下:pcr
实际上是一个 32 字节的寄存器,初始值为全 0,对于每种策略写入时,将当前 pcr
寄存器的值与策略的摘要值进行拼接后使用 SM3 进行哈希得到 pcr
的新值。FILE *file1=fopen("/home/player/tcmenv_question/src/test.txt","r");
int m=0,number;
char abc[33];
for(m=0;m<32;m++){
fscanf(file1,"%d",&number);
abc[m]=(char)number;
}
abc[32]=0;
if(memcmp(quote_report->nonce,abc,32)!=0)
{
strcpy(solve_result, "error");
}
else {
char zero[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
char research[32] = {0x81,0xe2,0x1b,0xc2,0x48,0x7c,0x1a,0x17,0x9f,0xfc,0xdb,0xd3,0x89,0xf6,0xc3,0xf1,0xa3,0x02,0xcd,0x26,0x8f,0x0c,0x93,0x78,0xd0,0x83,0x9f,0xc6,0xa0,0x8f,0xd5,0xea};
char product[32] = {0xb2,0x0a,0x7a,0x25,0xc7,0x31,0xd3,0x1b,0x1c,0x2f,0xdf,0xe7,0xcd,0xc4,0xc5,0x3f,0x84,0x6c,0x1b,0x9c,0x0e,0x49,0xbb,0x36,0x2b,0x73,0x41,0x5a,0xa3,0x84,0xce,0xab};
char test[32] = {0xed,0x7b,0x0f,0xd0,0xcb,0x59,0x0d,0x68,0xd6,0xb6,0xf1,0xfe,0x10,0x81,0x1e,0x57,0x7c,0xde,0x4f,0x74,0x17,0xef,0xc4,0xe8,0x59,0x93,0xe0,0xff,0x9a,0xbf,0x89,0x16};
char public[32] = {0x62,0xc8,0x08,0xfd,0x91,0x4c,0xe4,0x47,0x7b,0xc3,0xc5,0xe6,0x22,0x96,0x8b,0x5d,0x5f,0xbe,0xad,0xa4,0x45,0x7e,0x91,0x1f,0xa0,0x0d,0x34,0x4a,0xba,0xab,0x80,0x70};
char researchproduct[32] = {0x20,0x80,0xb4,0xb0,0xb3,0xba,0xc7,0xd2,0x86,0x42,0xb0,0xa9,0x54,0x9b,0xe2,0xdc,0x9e,0x77,0x54,0xb7,0x0d,0x3b,0x96,0x2d,0xbe,0xee,0xe3,0x1b,0x17,0xcb,0x88,0x43};
char researchtest[32] = {0x3e,0x0d,0x14,0x5e,0x2d,0xbe,0x16,0xba,0xa3,0x2b,0x8e,0xec,0xef,0xed,0x02,0xe7,0x45,0x82,0x94,0x7b,0x75,0xe5,0xbd,0xbb,0x42,0x3c,0xb1,0x71,0xc0,0xa5,0x33,0x3d};
char researchpublic[32] = {0xad,0x10,0x5b,0x3b,0x59,0xd2,0xde,0x78,0x55,0xa8,0x08,0xca,0x8a,0x74,0x63,0x72,0x62,0x57,0x38,0x23,0xfe,0xdb,0xcd,0x59,0xbd,0x28,0xfb,0x79,0x15,0x5f,0xb4,0x4d};
char researchtestpublic[32] = {0xdc,0xcb,0x92,0xf5,0x64,0x75,0xa7,0xa9,0xa3,0xd1,0x3d,0x49,0x0d,0x91,0x5a,0x97,0x9e,0xc4,0x4e,0x4c,0x7d,0xfb,0xf5,0x89,0x78,0x48,0xf4,0x98,0xe4,0x85,0x8c,0xdf};
char researchproductpublic[32] = {0x8f,0x8b,0x61,0x7d,0x08,0xf5,0xd2,0x0e,0x51,0xed,0xfd,0x96,0x50,0xb0,0x28,0x99,0xd4,0x69,0x75,0x09,0xe7,0xc7,0x7f,0xe4,0xa1,0x89,0xf9,0x94,0x97,0xcb,0x95,0x9a};
char researchproducttest[32] = {0xdd,0x86,0xde,0x23,0xac,0x9b,0x75,0x30,0xca,0x52,0xec,0x2a,0xc4,0x98,0x2f,0x07,0xdf,0x55,0xe4,0xbd,0xe5,0xa7,0xd5,0x98,0x78,0xab,0xa9,0x39,0x60,0x9e,0xa2,0x8e};
char producttest[32] = {0x2c,0x2d,0xc5,0x73,0xdc,0x11,0xac,0x66,0xb3,0x2c,0x33,0x7e,0x38,0x47,0xdd,0x9d,0x7e,0x6d,0x93,0x25,0xfd,0x8b,0x7f,0x1b,0xb6,0xb6,0x2f,0xcf,0xf6,0xa6,0x0e,0x5b};
char productpublic[32] = {0x0a,0x19,0xf1,0x13,0x98,0xce,0xdf,0xf0,0x9d,0x1c,0x35,0x95,0x60,0x26,0x97,0xaf,0x89,0x2b,0xdc,0x09,0xbd,0xdf,0x1e,0x9e,0x85,0xf0,0xa0,0x73,0x91,0xc3,0x54,0x5b};
char producttestpublic[32] = {0xc5,0x01,0xba,0x81,0x3c,0xa3,0x86,0x2a,0x3b,0xdf,0x14,0xa2,0x34,0x12,0x41,0xe9,0xe2,0x97,0x9f,0xee,0xaf,0x27,0x90,0x22,0x73,0x53,0x9f,0x8e,0x0f,0xde,0x4f,0x2a};
char testpublic[32] = {0xc8,0x11,0xe3,0x69,0x89,0xc2,0x50,0x9f,0xc1,0x9a,0xd3,0xc7,0xcf,0xac,0x5f,0x0f,0x69,0xfa,0x23,0xde,0x40,0xce,0x03,0x90,0x44,0x3b,0x68,0xdd,0xb1,0xde,0x9f,0x5f};
char researchproducttestpublic[32] = {0x6e,0x03,0x3d,0x5a,0x4d,0x38,0x3a,0x80,0x52,0xc2,0x4a,0x11,0xe1,0x22,0x77,0x43,0x88,0x0c,0x35,0x9d,0xfc,0x18,0x64,0x36,0x2c,0xcd,0xee,0x07,0x7b,0x10,0x6d,0x37};
if(memcmp(quote_report->pcrComp.pcrValue, zero, 32)==0) {
strcpy(solve_result,"null");
}
else if(memcmp(quote_report->pcrComp.pcrValue, research, 32)==0) {
strcpy(solve_result,"research");
}
else if(memcmp(quote_report->pcrComp.pcrValue, product, 32)==0) {
strcpy(solve_result,"product");
}
else if(memcmp(quote_report->pcrComp.pcrValue, test, 32)==0) {
strcpy(solve_result,"test");
}
else if(memcmp(quote_report->pcrComp.pcrValue, public, 32)==0) {
strcpy(solve_result,"public");
}
else if(memcmp(quote_report->pcrComp.pcrValue, researchproduct, 32)==0) {
strcpy(solve_result,"research|product");
}
else if(memcmp(quote_report->pcrComp.pcrValue, researchtest, 32)==0) {
strcpy(solve_result,"research|test");
}
else if(memcmp(quote_report->pcrComp.pcrValue, researchpublic, 32)==0) {
strcpy(solve_result,"research|public");
}
else if(memcmp(quote_report->pcrComp.pcrValue, researchtestpublic, 32)==0) {
strcpy(solve_result,"research|test|public");
}
else if(memcmp(quote_report->pcrComp.pcrValue, researchproductpublic, 32)==0) {
strcpy(solve_result,"research|product|public");
}
else if(memcmp(quote_report->pcrComp.pcrValue, researchproducttest, 32)==0) {
strcpy(solve_result,"research|product|test");
}
else if(memcmp(quote_report->pcrComp.pcrValue, producttest, 32)==0) {
strcpy(solve_result,"product|test");
}
else if(memcmp(quote_report->pcrComp.pcrValue, productpublic, 32)==0) {
strcpy(solve_result,"product|public");
}
else if(memcmp(quote_report->pcrComp.pcrValue, producttestpublic, 32)==0) {
strcpy(solve_result,"product|test|public");
}
else if(memcmp(quote_report->pcrComp.pcrValue, testpublic, 32)==0) {
strcpy(solve_result,"test|public");
}
else if(memcmp(quote_report->pcrComp.pcrValue, researchproducttestpublic, 32)==0) {
strcpy(solve_result,"research|product|test|public");
}
}
key_manage.c
中补全后运行 player.sh
即可得到 flag:三血队伍解法
作者:张子怡@北工大信安小队
操作内容:
1、 检查是否有重放攻击
external_data_store
全局变量中,只需和发来消息的随机数quote_report->nonce
对比。若相等则随机数是本轮生成的,没有重放。若不相等则有重放。int flag_error=0;
if(!memcmp(quote_report->nonce,external_data_store,DIGEST_SIZE)){
printf("!!!!!!!!!!!!no_replace!!!!!!!!!!!!!!!!!!n"); }
else{
printf("!!!!!!!!!!!!yes_replace!!!!!!!!!!!!!!!!!!n");
flag_error=1;
}
2、检查pcr值是否为0
int flag_null=0;
BYTE zero[DIGEST_SIZE];
memset(zero,0,DIGEST_SIZE);
if(!memcmp(quote_report->pcrComp.pcrValue,zero,DIGEST_SIZE)){
flag_null=1;
}
3、解析策略(并按照前面的两个判断来填写solve_result)
//获取value值
if (!strcmp(policy_digest - > name, research))
memcpy(re, policy_digest - > return_value, DIGEST_SIZE);
else if (!strcmp(policy_digest - > name, product))
memcpy(pro, policy_digest - > return_value, DIGEST_SIZE);
else if (!strcmp(policy_digest - > name, test))
memcpy(te, policy_digest - > return_value, DIGEST_SIZE);
else if (!strcmp(policy_digest - > name, public))
memcpy(pub, policy_digest - > return_value, DIGEST_SIZE);
else
printf("!!!!!!!!!!!!!!!!!!!!!!!!!n");
//解析策略值
///one
// memset(empty_digest,0,DIGEST_SIZE);
memcpy(empty_digest + DIGEST_SIZE, re2, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
if (!memcmp(empty_digest, quote_report - > pcrComp.pcrValue, DIGEST_SIZE)) strcpy(solve_result, "research");
memset(empty_digest, 0, DIGEST_SIZE);
memcpy(empty_digest + DIGEST_SIZE, pro, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
if (!memcmp(empty_digest, quote_report - > pcrComp.pcrValue, DIGEST_SIZE)) strcpy(solve_result, "product");
memset(empty_digest, 0, DIGEST_SIZE);
memcpy(empty_digest + DIGEST_SIZE, te, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
if (!memcmp(empty_digest, quote_report - > pcrComp.pcrValue, DIGEST_SIZE)) strcpy(solve_result, "test");
memset(empty_digest, 0, DIGEST_SIZE);
memcpy(empty_digest + DIGEST_SIZE, pub, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
if (!memcmp(empty_digest, quote_report - > pcrComp.pcrValue, DIGEST_SIZE)) strcpy(solve_result, "public");
///two
memset(empty_digest, 0, DIGEST_SIZE);
memcpy(empty_digest + DIGEST_SIZE, re2, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
memcpy(empty_digest + DIGEST_SIZE, pro, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
if (!memcmp(empty_digest, quote_report - > pcrComp.pcrValue, DIGEST_SIZE)) strcpy(solve_result, "research|product");
memset(empty_digest, 0, DIGEST_SIZE);
memcpy(empty_digest + DIGEST_SIZE, re2, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
memcpy(empty_digest + DIGEST_SIZE, te, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
if (!memcmp(empty_digest, quote_report - > pcrComp.pcrValue, DIGEST_SIZE)) strcpy(solve_result, "research|test");
memset(empty_digest, 0, DIGEST_SIZE);
memcpy(empty_digest + DIGEST_SIZE, re2, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
memcpy(empty_digest + DIGEST_SIZE, pub, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
if (!memcmp(empty_digest, quote_report - > pcrComp.pcrValue, DIGEST_SIZE)) strcpy(solve_result, "research|public");
memset(empty_digest, 0, DIGEST_SIZE);
memcpy(empty_digest + DIGEST_SIZE, pro, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
memcpy(empty_digest + DIGEST_SIZE, te, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
if (!memcmp(empty_digest, quote_report - > pcrComp.pcrValue, DIGEST_SIZE)) strcpy(solve_result, "product|test");
memset(empty_digest, 0, DIGEST_SIZE);
memcpy(empty_digest + DIGEST_SIZE, pro, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
memcpy(empty_digest + DIGEST_SIZE, pub, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
if (!memcmp(empty_digest, quote_report - > pcrComp.pcrValue, DIGEST_SIZE)) strcpy(solve_result, "product|pub");
memset(empty_digest, 0, DIGEST_SIZE);
memcpy(empty_digest + DIGEST_SIZE, te, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
memcpy(empty_digest + DIGEST_SIZE, pub, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
if (!memcmp(empty_digest, quote_report - > pcrComp.pcrValue, DIGEST_SIZE)) strcpy(solve_result, "test|public");
///three
memset(empty_digest, 0, DIGEST_SIZE);
memcpy(empty_digest + DIGEST_SIZE, re2, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
memcpy(empty_digest + DIGEST_SIZE, pro, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
memcpy(empty_digest + DIGEST_SIZE, te, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
if (!memcmp(empty_digest, quote_report - > pcrComp.pcrValue, DIGEST_SIZE)) strcpy(solve_result, "research|product|test");
memset(empty_digest, 0, DIGEST_SIZE);
memcpy(empty_digest + DIGEST_SIZE, re2, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
memcpy(empty_digest + DIGEST_SIZE, pro, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
memcpy(empty_digest + DIGEST_SIZE, pub, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
if (!memcmp(empty_digest, quote_report - > pcrComp.pcrValue, DIGEST_SIZE)) strcpy(solve_result, "research|product|public");
memset(empty_digest, 0, DIGEST_SIZE);
memcpy(empty_digest + DIGEST_SIZE, re2, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
memcpy(empty_digest + DIGEST_SIZE, te, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
memcpy(empty_digest + DIGEST_SIZE, pub, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
if (!memcmp(empty_digest, quote_report - > pcrComp.pcrValue, DIGEST_SIZE)) strcpy(solve_result, "research|test|public");
memset(empty_digest, 0, DIGEST_SIZE);
memcpy(empty_digest + DIGEST_SIZE, pro, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
memcpy(empty_digest + DIGEST_SIZE, te, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
memcpy(empty_digest + DIGEST_SIZE, pub, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
if (!memcmp(empty_digest, quote_report - > pcrComp.pcrValue, DIGEST_SIZE)) strcpy(solve_result, "product|test|public");
///four
memset(empty_digest, 0, DIGEST_SIZE);
memcpy(empty_digest + DIGEST_SIZE, re2, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
memcpy(empty_digest + DIGEST_SIZE, pro, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
memcpy(empty_digest + DIGEST_SIZE, te, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
memcpy(empty_digest + DIGEST_SIZE, pub, DIGEST_SIZE);
calculate_context_sm3(empty_digest, 2 * DIGEST_SIZE, empty_digest);
if (!memcmp(empty_digest, quote_report - > pcrComp.pcrValue, DIGEST_SIZE)) strcpy(solve_result, "research|product|test|public");
if (flag_error == 1) strcpy(solve_result, "error");
if (flag_null == 1) strcpy(solve_result, "null ");
相关阅读
赛前热身|「第十六届全国大学生信息安全竞赛」安全可信赛题介绍
赛前热身第2期|「第十六届全国大学生信息安全竞赛」安全可信赛题
赛前热身第3期|「第十六届全国大学生信息安全竞赛」安全可信赛题
+ + + + + + + + + + +
原文始发于微信公众号(春秋伽玛):官方WP | 关于“可信度量”赛题的设计与思考