【CYBRICS】Polyglot WriteUp


这道题有毒。。。

附件是一个.c源代码

我们自己写一下代码跑一下,把key直接写死

int main() {
	char flagged[] = { ...... };
	char key[] = "mod3r0d!";
	unsigned long long val = *(unsigned long long*)key;
	unsigned long long *ptr = (unsigned long long*)flagged;
	while (*ptr != 0) {
		*ptr = *ptr ^ val;
		ptr += 1;
	}
	puts(flagged);
}

跑出来是另一段源码

#include <iostream>
template <unsigned int a, unsigned int b>
struct t1 {
        enum { value = b + t1<a-1, b>::value };
};
template <unsigned int b>
struct t1<0, b> {
        enum { value = 0 };
};
template <unsigned int a, unsigned int b>
struct t2 {
        enum { value = 1 + t2<a-1, b>::value };
};
template <unsigned int b>
struct t2<0, b> {
        enum { value = 1 + t2<0, b-1>::value };
};
template<>
struct t2<0, 0>{
    enum { value = 0};
};
void decode(unsigned char *data, unsigned int val){
    unsigned int *ptr = reinterpret_cast<unsigned int *>(data);
    while (*ptr != 0) {
        *ptr = *ptr ^ val;
        val = (val ^ (val << 1)) ^ 0xc2154216;
        ptr += 1;
    }
}
unsigned char flagged[] = { ...... };
int main(){
    decode(flagged, t2<0xcaca0000, t2<444, t1<t2<100, t1<4,3>::value>::value, t2<44, t1<11,3>::value>::value>::value>::value>::value);
    std::cout << flagged <<std::endl;
}

我们对源码稍做改动

unsigned int t1(unsigned int a, unsigned int b) {
	if (a == 0)
		return 0;
	return b + t1(a - 1, b);
}

unsigned int t2(unsigned int a, unsigned int b) {
	if (a == 0) {
		if (b == 0)
			return 0;
		else
			return 1 + t2(0, b - 1);
	}
	return 1 + t2(a - 1, b);
}

void decode(unsigned char *data, unsigned int val) {
	unsigned int *ptr = reinterpret_cast<unsigned int *>(data);
	while (*ptr != 0) {
		*ptr = *ptr ^ val;
		val = (val ^ (val << 1)) ^ 0xc2154216;
		ptr += 1;
	}
}

unsigned char flagged[] = { ...... };

int main() {
	unsigned int tmp = t2(444, t1(t2(100, t1(4, 3)), t2(44, t1(11, 3))));
	// tmp = 9068
	// t2(0xcaca0000, tmp)
	decode(flagged, 0xcaca0000 + 9068);
	cout << flagged << endl;
}

我把模板结构体改成了函数
注意到最外层的t2递归太多次了,会爆栈,不过它的逻辑很简单,就是a+b,因此计算出tmp的值硬编码进去即可
这次运行会打印出python源码

import types

def define_func(argcount, nlocals, code, consts, names):
    #PYTHON3.8!!!
    def inner():
        return 0

    fn_code = inner.__code__
    cd_new = types.CodeType(argcount,
                             0,
                             fn_code.co_kwonlyargcount,
                             nlocals,
                             1024,
                             fn_code.co_flags,
                             code,
                             consts,
                             names,
                             tuple(["v%d" for i in range(nlocals)]),
                             fn_code.co_filename,
                             fn_code.co_name,
                             fn_code.co_firstlineno,
                             fn_code.co_lnotab,
                             fn_code.co_freevars,
                             fn_code.co_cellvars)
    inner.__code__ = cd_new
    return inner

f1 = define_func(2,2,b'|\x00|\x01k\x02S\x00', (None,), ())
f2 = define_func(1,1,b't\x00|\x00\x83\x01S\x00', (None,), ('ord',))
f3 = define_func(0,0,b't\x00d\x01\x83\x01S\x00', (None,  'Give me flag: '), ('input',))
f4 = define_func(1, 3, b'd\x01d\x02d\x03d\x04d\x05d\x01d\x06d\x07d\x08d\td\x03d\nd\x0bd\x0cd\rd\x08d\x0cd\x0ed\x0cd\x0fd\x0ed\x10d\x11d\td\x12d\x03d\x10d\x03d\x0ed\x13d\x0bd\nd\x14d\x08d\x13d\x01d\x01d\nd\td\x01d\x12d\x0bd\x10d\x0fd\x14d\x03d\x0bd\x15d\x16g1}\x01t\x00|\x00\x83\x01t\x00|\x01\x83\x01k\x03r\x82t\x01d\x17\x83\x01\x01\x00d\x18S\x00t\x02|\x00|\x01\x83\x02D\x00]$}\x02t\x03|\x02d\x19\x19\x00t\x04|\x02d\x1a\x19\x00\x83\x01\x83\x02d\x18k\x02r\x8c\x01\x00d\x18S\x00q\x8cd\x1bS\x00',
                 (None, 99, 121, 98, 114, 105, 115, 123, 52, 97, 100, 51, 101, 55, 57, 53, 54, 48, 49, 50, 56, 102, 125, 'Length mismatch!', False, 1, 0, True),
                 ('len', 'print', 'zip', 'f1', 'f2'))
f5 = define_func(0, 1,b't\x00\x83\x00}\x00t\x01|\x00\x83\x01d\x01k\x08r\x1ct\x02d\x02\x83\x01\x01\x00n\x08t\x02d\x03\x83\x01\x01\x00d\x00S\x00',(None, False, 'Nope!', 'Yep!'), ('f3', 'f4', 'print'))
f5()

emmm…看起来好像很复杂的样子

不过值得庆幸的是,在上次的ctf比赛中我认识了一个叫dis的python库,没想到这么快就用上了
先对f5进行dis

import dis

print(dis.dis(f5))

得到的结果是

  7           0 LOAD_GLOBAL              0 (f3)
              2 CALL_FUNCTION            0
              4 STORE_FAST               0 (v%d)
              6 LOAD_GLOBAL              1 (f4)
              8 LOAD_FAST                0 (v%d)
             10 CALL_FUNCTION            1
             12 LOAD_CONST               1 (False)
             14 COMPARE_OP               8 (is)
             16 POP_JUMP_IF_FALSE       28
             18 LOAD_GLOBAL              2 (print)
             20 LOAD_CONST               2 ('Nope!')
             22 CALL_FUNCTION            1
             24 POP_TOP
             26 JUMP_FORWARD             8 (to 36)
        >>   28 LOAD_GLOBAL              2 (print)
             30 LOAD_CONST               3 ('Yep!')
             32 CALL_FUNCTION            1
             34 POP_TOP
        >>   36 LOAD_CONST               0 (None)
             38 RETURN_VALUE
None

看不懂伪代码的可以上网搜一下,个人感觉比较容易看清楚逻辑了

可以看出,主要逻辑在f4中,因此对f4进行dis

import dis

print(dis.dis(f4))

得到的结果是

  7           0 LOAD_CONST               1 (99)
              2 LOAD_CONST               2 (121)
              4 LOAD_CONST               3 (98)
              6 LOAD_CONST               4 (114)
              8 LOAD_CONST               5 (105)
             10 LOAD_CONST               1 (99)
             12 LOAD_CONST               6 (115)
             14 LOAD_CONST               7 (123)
             16 LOAD_CONST               8 (52)
             18 LOAD_CONST               9 (97)
             20 LOAD_CONST               3 (98)
             22 LOAD_CONST              10 (100)
             24 LOAD_CONST              11 (51)
             26 LOAD_CONST              12 (101)
             28 LOAD_CONST              13 (55)
             30 LOAD_CONST               8 (52)
             32 LOAD_CONST              12 (101)
             34 LOAD_CONST              14 (57)
             36 LOAD_CONST              12 (101)
             38 LOAD_CONST              15 (53)
             40 LOAD_CONST              14 (57)
             42 LOAD_CONST              16 (54)
             44 LOAD_CONST              17 (48)
             46 LOAD_CONST               9 (97)
             48 LOAD_CONST              18 (49)
             50 LOAD_CONST               3 (98)
             52 LOAD_CONST              16 (54)
             54 LOAD_CONST               3 (98)
             56 LOAD_CONST              14 (57)
             58 LOAD_CONST              19 (50)
             60 LOAD_CONST              11 (51)
             62 LOAD_CONST              10 (100)
             64 LOAD_CONST              20 (56)
             66 LOAD_CONST               8 (52)
             68 LOAD_CONST              19 (50)
             70 LOAD_CONST               1 (99)
             72 LOAD_CONST               1 (99)
             74 LOAD_CONST              10 (100)
             76 LOAD_CONST               9 (97)
             78 LOAD_CONST               1 (99)
             80 LOAD_CONST              18 (49)
             82 LOAD_CONST              11 (51)
             84 LOAD_CONST              16 (54)
             86 LOAD_CONST              15 (53)
             88 LOAD_CONST              20 (56)
             90 LOAD_CONST               3 (98)
             92 LOAD_CONST              11 (51)
             94 LOAD_CONST              21 (102)
             96 LOAD_CONST              22 (125)
             98 BUILD_LIST              49
            100 STORE_FAST               1 (v%d)
            102 LOAD_GLOBAL              0 (len)
            104 LOAD_FAST                0 (v%d)
            106 CALL_FUNCTION            1
            108 LOAD_GLOBAL              0 (len)
            110 LOAD_FAST                1 (v%d)
            112 CALL_FUNCTION            1
            114 COMPARE_OP               3 (!=)
            116 POP_JUMP_IF_FALSE      130
            118 LOAD_GLOBAL              1 (print)
            120 LOAD_CONST              23 ('Length mismatch!')
            122 CALL_FUNCTION            1
            124 POP_TOP
            126 LOAD_CONST              24 (False)
            128 RETURN_VALUE
        >>  130 LOAD_GLOBAL              2 (zip)
            132 LOAD_FAST                0 (v%d)
            134 LOAD_FAST                1 (v%d)
            136 CALL_FUNCTION            2
            138 GET_ITER
        >>  140 FOR_ITER                36 (to 178)
            142 STORE_FAST               2 (v%d)
            144 LOAD_GLOBAL              3 (f1)
            146 LOAD_FAST                2 (v%d)
            148 LOAD_CONST              25 (1)
            150 BINARY_SUBSCR
            152 LOAD_GLOBAL              4 (f2)
            154 LOAD_FAST                2 (v%d)
            156 LOAD_CONST              26 (0)
            158 BINARY_SUBSCR
            160 CALL_FUNCTION            1
            162 CALL_FUNCTION            2
            164 LOAD_CONST              24 (False)
            166 COMPARE_OP               2 (==)
            168 POP_JUMP_IF_FALSE      140
            170 POP_TOP
            172 LOAD_CONST              24 (False)
            174 RETURN_VALUE
            176 JUMP_ABSOLUTE          140
        >>  178 LOAD_CONST              27 (True)
            180 RETURN_VALUE
None

就是很简单的比较字符串
把前面的一大串const打印出来即可

int main() {
	char flag[] = { 99,121,98,114,105,99,115,123,52,97,98,100,51,101,55,52,101,57,101,53,57,54,48,97,49,98,54,98,57,50,51,100,56,52,50,99,99,100,97,99,49,51,54,53,56,98,51,102,125,0 };
	cout << flag;
}

吐个槽:题目的名字的中文意思是“通晓多种语言的人”,我还以为会套很多娃,结果就俩啊。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值