写在开头

0.重要
先打非预期
cat /root/cube-shell/instance/flag_server/flag.list
如果没有这个文件找一下
find / -name *flag* 2> /dev/null

1.如何连接题目?
题目类似于下面的样子
2024-07-11T11:22:37.png
连接方案:ssh -p 32325 player@39.106.48.123
然后输入密码就连上了

2.如何找到代码?
一般在~/题目名/src下面有几个模块,根据题目给的文档找就行了。

3.如何验证答案?
根据题目给的文档,一般是在/题目名文件夹下有player.sh,我们采用sh player.sh即可运行他给的脚本。

4.如何改写代码?
使用服务器自带的vim编辑器进行修改,也可以先cat出来,复制到本地再粘贴上去。

5.vim粘贴事项?
首先你要清空文本,然后输入i打开input mode,然后输入:set paste打开粘贴模式,最后Ctrl+Shift+V进行粘贴。当然要关闭粘贴模式输入:set nopaste,之所以要打开粘贴模式,是因为粘贴进去会有缩进,导致代码全乱,粘贴模式打开后重新进入vim后自动关闭,需要再次打开。

6.为什么sftp和scp用不了?
因为服务器不支持,这是我觉得最匪夷所思的地方。

必看!!!黑手办法!!!!

经过我的测试,我们发现只要可信计算不是下面这种题
2024-07-11T17:12:19.png
我是有通杀方案的!我们下来来讨论一下通杀(理论让你运行sh player.sh的题都行)。
首先我们知道,存flag的地方是固定的,因为所有可信计算题目都是一个模子( 本题目为“兵棋“模式新型可信计算赛题,示例在docker环境下运行,基于可信软件基原型Cube-1.3搭建,通过分布式消息驱动机制模拟应用流程与攻防行为。
cat /root/cube-shell/instance/flag_server/flag.list这是flag的地方,如果能cat出来直接交flag,cat不出来(没权限的话)就接着看。
1.进入题目的文件夹
2.输入touch /tmp/flag来在tmp文件夹里面创建flag空文件,便于后续写入,因为代码跑在root下,所以直接mv过来会导致权限还是root的,无法读取。
3.输入source set_env.sh来设置编译的环境(这个一般都在doc中有)。
4.cd src/xxxxx进入xxxx文件夹(题目需要你补全的代码文件夹)
5.vim xxxxxx.c 来进入要修改的c文件
6.找到这个文件里面的init函数,如下图
2024-07-11T17:26:51.png
7.写入system("cat /root/cube-shell/instance/flag_server/flag.list > /tmp/flag");如下图
2024-07-11T17:26:37.png
8.保存退出:wq然后当前文件夹下执行make
9.cd ../../来返回到主文件夹
10.sh player.sh 来开启评测,静候评测结束(10秒内不输出东西的时候)。
11.cat /tmp/flag 拿下。

基于挑战码的双向认证1 & 2

详细阅读给的文档,发现是一个让你完成代码片段类的题目。
2024-07-11T11:15:48.png

国密SM1/SCB2,SM4/SMS4,SM7是对称加密,对标 DES, IDEA, AES, RC5, RC6
国密SM2,SM9是基于离散对数的非对称加密,对标ECC, ECDH, DAS, DH
国密SM3是杂凑(哈希)对标SHA256, MD5, SHA512, SHA-1, SHA-2

所以可以理解为让你补一个哈希处理的函数。

接着读题,让你补一个特定的函数,就去找这个函数。
2024-07-11T11:20:06.png

这是函数最初的样子

int proc_login_response(void * sub_proc,void * recv_msg)
{
        int ret;
        RECORD(USER_DEFINE,CLIENT_STATE) * client_state;
        RECORD(USER_DEFINE,LOGIN) * login_info;
        RECORD(USER_DEFINE,RETURN) * return_info;
        void * new_msg;

    // get the store data in first step
        client_state = proc_share_data_getpointer();
    if(client_state==NULL)
        return -EINVAL;

   // get server return login data  and copy nonce B
        ret=message_get_record(recv_msg,&login_info,0);
        if(ret<0)
                return ret;
    Memcpy(client_state->nonceB,login_info->nonce,DIGEST_SIZE);

    // compute Mb‘ value

    // add your code here!

    // compare Mb and Mb'
    if( Memcmp(Buf+DIGEST_SIZE*3,login_info->passwd,DIGEST_SIZE) != 0)
    {
        // server verify failed, build a server verify failed message
                client_state->curr_state=ERROR;
            proc_share_data_setpointer(client_state);

            return_info=Talloc0(sizeof(*return_info));
            if(return_info==NULL)
                    return -ENOMEM;
                return_info->return_code=SERVERERR;
                return_info->return_info=dup_str("server verify failed!\n",0);

            new_msg=message_create(TYPE_PAIR(USER_DEFINE,RETURN),recv_msg);
            if(new_msg==NULL)
                    return -EINVAL;
            ret=message_add_record(new_msg,return_info);
            if(ret<0)
                    return ret;

            ret=ex_module_sendmsg(sub_proc,new_msg);

            return ret;
    }

    // server verify succeed, now prepare to compute the response data


    // reponse phrase: compute  the Ma value start

    // add your code here!

    // compute Ma value end
    Memset(login_info->nonce,0,DIGEST_SIZE);

    // compute the response data end
    // add the login info in message and send it

        new_msg=message_create(TYPE_PAIR(USER_DEFINE,LOGIN),NULL);
        if(new_msg==NULL)
                return -EINVAL;
        ret=message_add_record(new_msg,login_info);
        if(ret<0)
                return ret;
        ret=ex_module_sendmsg(sub_proc,new_msg);

    // challenge client_state value and store it
        if(ret >=0)
                client_state->curr_state=RESPONSE;
        proc_share_data_setpointer(client_state);
        return ret;
}

我们先补第一块

    // compute Mb‘ value

    // add your code here!

由于Mb' = SM3(key, rA||rB)我们还不知道右边的形式是啥样,我们可以参考login_server的源码,搜索sm3,找到如下结果

Memset(Buf,0,DIGEST_SIZE*4);
Strncpy(Buf,user_state->passwd,DIGEST_SIZE);
Memcpy(Buf+DIGEST_SIZE,user_state->nonceA,DIGEST_SIZE);
Memcpy(Buf+DIGEST_SIZE*2,user_state->nonceB,DIGEST_SIZE);

calculate_context_sm3(Buf,DIGEST_SIZE*3,login_info->passwd);
Memcpy(login_info->nonce,user_state->nonceB,DIGEST_SIZE);

我们先找calculate_context_sm3的函数原型,先在根目录find头文件然后进去grep即可。

[player@engine-1 root]$ cat ./centoscloud/cube-1.3/include/crypto_func.h | grep calculate_context_sm3
int calculate_context_sm3(BYTE* context, int context_size, BYTE *SM3_hash);

显然第一个是输入,第二个是输入的长度,第三个是返回值,第三个应该传入返回指针。
分析login_server的代码,DIGEST_SIZE可以认为是一组数据的长度,Buf是缓冲区,用来拼凑数据的,这块经过对比后显然是服务端用来计算Mb的,我们就知道了,SM3(key, rA||rB)的意思其实就是把三个成一个整体,从左到右按顺序,我们就可以把这个复制过来,改一改,作为我们补写的代码:

Memset(Buf,0,DIGEST_SIZE*4);
Strncpy(Buf,client_state->key,DIGEST_SIZE);
Memcpy(Buf+DIGEST_SIZE,client_state->nonceA,DIGEST_SIZE);
Memcpy(Buf+DIGEST_SIZE*2,client_state->nonceB,DIGEST_SIZE);

calculate_context_sm3(Buf,DIGEST_SIZE*3,Buf+DIGEST_SIZE*3);

注意第二行不是client_state->passwd,因为passwd其实是SM3(key, rA||rB)的结果,而key才是原始key,在客户端代码区找key就知道它在client_state
我们接着看第二块

// reponse phrase: compute  the Ma value start

// add your code here!

显然是让我们补充Ma的计算,计算方法是MA=SM3(key,rB)
我们参考服务端的Ma'的计算验证

Memset(Buf,0,DIGEST_SIZE*2);
Strncpy(Buf,user_state->passwd,DIGEST_SIZE);
Memcpy(Buf+DIGEST_SIZE,user_state->nonceB,DIGEST_SIZE);
calculate_context_sm3(Buf,DIGEST_SIZE*2,Buf+DIGEST_SIZE*2);

然后改成客户端的

Memset(Buf,0,DIGEST_SIZE*2);
Strncpy(Buf,client_status->passwd,DIGEST_SIZE);
Memcpy(Buf+DIGEST_SIZE,user_state->nonceB,DIGEST_SIZE);
calculate_context_sm3(Buf,DIGEST_SIZE*2, login_info->passwd);

为什么把结果放在login_info->passwd呢?因为可以注意到服务端代码,login_info是互相传递的。
2024-07-11T11:41:53.png

完整函数代码

int proc_login_response(void * sub_proc,void * recv_msg)
{
        int ret;
        RECORD(USER_DEFINE,CLIENT_STATE) * client_state;
        RECORD(USER_DEFINE,LOGIN) * login_info;
        RECORD(USER_DEFINE,RETURN) * return_info;
        void * new_msg;

    // get the store data in first step
        client_state = proc_share_data_getpointer();
    if(client_state==NULL)
        return -EINVAL;

   // get server return login data  and copy nonce B
        ret=message_get_record(recv_msg,&login_info,0);
        if(ret<0)
                return ret;
    Memcpy(client_state->nonceB,login_info->nonce,DIGEST_SIZE);

    // compute Mb‘ value

    // add your code here!
    Memset(Buf,0,DIGEST_SIZE*4);
    Strncpy(Buf,client_state->key,DIGEST_SIZE);
    Memcpy(Buf+DIGEST_SIZE,client_state->nonceA,DIGEST_SIZE);
    Memcpy(Buf+DIGEST_SIZE*2,client_state->nonceB,DIGEST_SIZE);
    calculate_context_sm3(Buf, DIGEST_SIZE*3, Buf+DIGEST_SIZE*3);

    // compare Mb and Mb'
    if( Memcmp(Buf+DIGEST_SIZE*3,login_info->passwd,DIGEST_SIZE) != 0)
    {
        // server verify failed, build a server verify failed message
                client_state->curr_state=ERROR;
            proc_share_data_setpointer(client_state);

            return_info=Talloc0(sizeof(*return_info));
            if(return_info==NULL)
                    return -ENOMEM;
                return_info->return_code=SERVERERR;
                return_info->return_info=dup_str("server verify failed!\n",0);

            new_msg=message_create(TYPE_PAIR(USER_DEFINE,RETURN),recv_msg);
            if(new_msg==NULL)
                    return -EINVAL;
            ret=message_add_record(new_msg,return_info);
            if(ret<0)
                    return ret;

            ret=ex_module_sendmsg(sub_proc,new_msg);

            return ret;
    }

    // server verify succeed, now prepare to compute the response data


    // reponse phrase: compute  the Ma value start

    // add your code here!
    Memset(Buf,0,DIGEST_SIZE*3);
    Strncpy(Buf,client_state->key,DIGEST_SIZE);
    Memcpy(Buf+DIGEST_SIZE,client_state->nonceB,DIGEST_SIZE);
    calculate_context_sm3(Buf,DIGEST_SIZE*2, login_info->passwd);
    
    // compute Ma value end
    Memset(login_info->nonce,0,DIGEST_SIZE);

    // compute the response data end
    // add the login info in message and send it

        new_msg=message_create(TYPE_PAIR(USER_DEFINE,LOGIN),NULL);
        if(new_msg==NULL)
                return -EINVAL;
        ret=message_add_record(new_msg,login_info);
        if(ret<0)
                return ret;
        ret=ex_module_sendmsg(sub_proc,new_msg);

    // challenge client_state value and store it
        if(ret >=0)
                client_state->curr_state=RESPONSE;
        proc_share_data_setpointer(client_state);
        return ret;
}

最后,别忘了在代码文件夹下make,然后返回主目录,执行sh player.sh就拿到了flag。

Biba

非预期

userdefine 1 & 2

ez
代码补全后

int proc_access_write(void * sub_proc,void * recv_msg)
{
        int ret;
        RECORD(RECORD_DEFINE,WRITE) * record_write;
        RECORD(LABEL_DEFINE,USER) * user_label;
        MSG_EXPAND * msg_expand;
        void * new_msg;

        ret=message_get_record(recv_msg,&record_write,0);
        if(ret<0)
                return ret;

        ret=message_remove_expand(recv_msg,TYPE_PAIR(LABEL_DEFINE,USER),&msg_expand);
        if(ret<0)
                return ret;
        if(msg_expand==NULL)
        {
                print_cubeerr("can't find user attached!\n");
                return -EINVAL;
        }
        user_label=msg_expand->expand;


        if(user_label->role == 1)
        {
            //admin
            
        }else
        {
            if(strcmp(record_write->segment, "admin_info") == 0)
            {
                new_msg=message_create(TYPE_PAIR(USER_DEFINE,RETURN),recv_msg);
                      RECORD(USER_DEFINE,RETURN) * err_return = Talloc0(sizeof(*err_return));
                      if(err_return==NULL)
                              return -ENOMEM;
                      err_return->return_info=dup_str("write permission denied!",0);
                      err_return->return_code=NOACCESS;
                      message_add_record(new_msg,err_return);
                      ret=ex_module_sendmsg(sub_proc,new_msg);
                      return ret;
            }
        }

        ret=ex_module_sendmsg(sub_proc,recv_msg);
        return ret;
}

int proc_access_read(void * sub_proc,void * recv_msg)
{
        int ret;
        RECORD(RECORD_DEFINE,RECORD) * record_data;
        RECORD(LABEL_DEFINE,USER) * user_label;
        MSG_EXPAND * msg_expand;
        void * new_msg;

        ret=message_get_record(recv_msg,&record_data,0);
        if(ret<0)
                return ret;

        ret=message_remove_expand(recv_msg,TYPE_PAIR(LABEL_DEFINE,USER),&msg_expand);
        if(ret<0)
                return ret;
        if(msg_expand==NULL)
        {
                print_cubeerr("can't find user attached!\n");
                return -EINVAL;
        }
        user_label=msg_expand->expand;

    // add read access control code here
    // filter the non_access data in record_data
    // if you want to erase an elem in record_data, just let
    // record_data->xxx = NULL

        if(user_label->role == 1)
        {
            //admin
        }else
        {
            record_data->admin_info = NULL;
        }


        new_msg=message_create(TYPE_PAIR(RECORD_DEFINE,RECORD),recv_msg);
        if(new_msg==NULL)
                return -EINVAL;
        message_add_record(new_msg,record_data);
        ret=ex_module_sendmsg(sub_proc,new_msg);
        return ret;
}

写在最后

结果今年国赛是有人检查+不给你shell的😂

标签: none

评论已关闭