内容简介:今天是很特别的一天呢,七月一日,一周的第一天,一月的第一天,下半年第一天,建党98周年,香港回归的22周年。小伙伴们周末愉快玩耍时,有没有看我们公布的KCTF英雄榜单呢?你是否榜上有名呢?一路走来,我们接到神秘来信,唤醒沉睡的敦煌,破解金字塔的诅咒,打开神秘的达芬奇密码,昨天我们一起探索了丛林的秘密,今天让我们一起来解析第六题,寻找消失的岛屿~
今天是很特别的一天呢,七月一日,一周的第一天,一月的第一天,下半年第一天,建党98周年,香港回归的22周年。
小伙伴们周末愉快玩耍时,有没有看我们公布的KCTF英雄榜单呢?你是否榜上有名呢?
一路走来,我们接到神秘来信,唤醒沉睡的敦煌,破解金字塔的诅咒,打开神秘的达芬奇密码,昨天我们一起探索了丛林的秘密,今天让我们一起来解析第六题,寻找消失的岛屿~
题目背景:
走出森林,是洁白的沙滩,湛蓝的海水,和晒太阳的螃蟹。远处影影绰绰的有几座小岛。突然,浓墨色的黑烟正在慢慢的向这边的天空渲染。外星人的战舰在黑云中若隐若现,并越发密集。远方的岛屿正在慢慢沉入海水之中,脚下的沙滩也慢慢的被海水覆盖,海水正在吞噬这些岛屿,留给我们的时间不多了。
在这些众多的岛屿之中,究竟哪一个藏了宝石?你又该怎样前往这些岛屿呢?
本题共有2170人围观,最终有153支团队攻破成功。这道题是除第一题外,攻破人数最多的一道题,相对来说,这道题还是比较简单的。
攻破此题的战队排名一览:
接下来我们来对题目进行解析,破解其中的奥秘。
本题考查了修改过编码table的base64算法,重点在于单个字符的变换强度。真实的编码table从头到尾不会在内存中显示。所以攻击者需要先将断点设置在charEncrypt处,找出编码的变换规则,然后找到修改过后的编码table,根据变换规则推导出真正的编码table。
本题出题战队 iret :
iret 团队简介:某安全公司实习生,目前正在学习逆向和木马分析,希望能从各位大佬身上学习并提升自己。
该题目为base64魔改的CrackMe。
首先定义了一个自定义的base64编码table:
#define TABLE1 "tuvwxTUlmnopqrs7YZabcdefghij8yz0123456VWXkABCDEFGHIJKLMNOPQRS9+/"
然后定义了一个单个字符加密的方法:
static char charEncrypt(int data) { char *table = TABLE1; data = table[data]; if(data>=65 && data<=90) { data = (155-data) ; return (char)data; } if(data>=97&&data<=122) { data = (data-64); return (char)data; } if(data>=48&&data<=57) { data = (data + 50) ; return (char)data; } if(data==43) { data = 119; return (char)data; } if(data==47) data = 121; return (char)data; }
接下来使用 c语言 实现了base64编码,不仅使用修改后的编码table,还会在赋值的时候调用单个字符加密方法将字符加密后赋值。
破解思路:
本题的重点在于单个字符的变换强度。真实的编码table从头到尾不会在内存中显示。所以攻击者需要先将断点设置在charEncrypt处,找出编码的变换规则,然后找到修改过后的编码table,根据变换规则推导出真正的编码table。
完整代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <inttypes.h> #define TABLE1 "tuvwxTUlmnopqrs7YZabcdefghij8yz0123456VWXkABCDEFGHIJKLMNOPQRS9+/" /*base64编/解码用的基础字符集*/ static char charEncrypt(int data) { char *table = TABLE1; data = table[data]; if(data>=65 && data<=90) { data = (155-data) ; return (char)data; } if(data>=97&&data<=122) { data = (data-64); return (char)data; } if(data>=48&&data<=57) { data = (data + 50) ; return (char)data; } if(data==43) { data = 119; return (char)data; } if(data==47) data = 121; return (char)data; } static int base64_encode( const uint8_t *bindata, char *base64, int binlength) { int i, j; uint8_t current; for ( i = 0, j = 0 ; i < binlength ; i += 3 ) { current = (bindata[i] >> 2) ; current &= (uint8_t)0x3F; base64[j++] = charEncrypt((int)current); current = ( (uint8_t)(bindata[i] << 4 ) ) & ( (uint8_t)0x30 ) ; if ( i + 1 >= binlength ) { base64[j++] = charEncrypt((int)current); base64[j++] = '='; base64[j++] = '='; break; } current |= ( (uint8_t)(bindata[i+1] >> 4) ) & ( (uint8_t) 0x0F ); base64[j++] = charEncrypt((int)current); current = ( (uint8_t)(bindata[i+1] << 2) ) & ( (uint8_t)0x3C ) ; if ( i + 2 >= binlength ) { base64[j++] = charEncrypt((int)current); base64[j++] = '='; break; } current |= ( (uint8_t)(bindata[i+2] >> 6) ) & ( (uint8_t) 0x03 ); base64[j++] = charEncrypt((int)current); current = ( (uint8_t)bindata[i+2] ) & ( (uint8_t)0x3F ) ; base64[j++] = charEncrypt((int)current); } base64[j] = '\0'; return j; } int main (int argc, char **argv) { char str1[55]; printf("please enter Serial:"); scanf(" %s",str1); if(strlen(str1)>=50) { printf("error\n"); exit; } char *base64_str = calloc(1, 1024); base64_encode(str1, base64_str, strlen(str1)); char *str = "!NGV%,$h1f4S3%2P(hkQ94=="; if(!strcmp(str,base64_str)) { printf("Success\n"); } else{ printf("Please Try Again\n"); } free(base64_str); system("pause"); return 0; }
本题解题思路由看雪论坛 qwertyaa 提供:
可以看到这个程序主要是 BASE64 的变体,它里面的 charEncrypt 如下:
char from[]="tuvwxTUlmnopqrs7YZabcdefghij8yz0123456VWXkABCDEFGHIJKLMNOPQRS9+/"; char charEncrypt(char data) { char dataa; dataa = from[data]; if ( dataa > '@' && dataa <= 'Z' ) return -101 - dataa; if ( dataa > '`' && dataa <= 'z' ) return dataa - 64; if ( dataa > '/' && dataa <= '9' ) return dataa + 50; if ( dataa == '+' ) return 'w'; if ( dataa == '/' ) dataa = 'y'; return dataa; }
而普通的 BASE64 的 charEncrypt 如下:
char reb[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; char charEncrypt(char data) { char dataa; dataa = reb[data]; return dataa; }
两个 charEncrypt 都是置换,对每个字符求第一个置换的逆置换后进行第二个置换的结果即可,代码如下:
#include <bits/stdc++.h> using namespace std; char reb[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; char from[]="tuvwxTUlmnopqrs7YZabcdefghij8yz0123456VWXkABCDEFGHIJKLMNOPQRS9+/"; char result[]="!NGV%,$h1f4S3%2P(hkQ94=="; char charEncrypt(char data) { char dataa; dataa = from[data]; if ( dataa > '@' && dataa <= 'Z' ) return -101 - dataa; if ( dataa > '`' && dataa <= 'z' ) return dataa - 64; if ( dataa > '/' && dataa <= '9' ) return dataa + 50; if ( dataa == '+' ) return 'w'; if ( dataa == '/' ) dataa = 'y'; return dataa; } char re[256]; int main(){ for(int i=0;i<strlen(reb);i++){ re[charEncrypt(i)]=i; } int len=strlen(result); for(int i=0;i<len;i++)if(result[i]!='='){ result[i]=reb[re[result[i]]]; } puts(result); }
将结果用 javascript 的 atob 函数解码得FLAG: KanXue2019ctf_st。
▲
END
1、 【英雄榜单】看雪.纽盾 KCTF 晋级赛Q2 排行榜出炉!
2、 看雪.纽盾 KCTF 2019 Q2 | 第一题点评及解题思路
3、看雪.纽盾 KCTF 2019 Q2 | 第二题点评及解题思路
4、 看雪.纽盾 KCTF 2019 Q2 | 第三题点评及解题思路
5、 看雪.纽盾 KCTF 2019 Q2 | 第四题点评及解题思路
6、 看雪.纽盾 KCTF 2019 Q2 | 第五题点评及解题思路
主办方
看雪学院(www.kanxue.com)是一个专注于PC、移动、智能设备安全研究及逆向工程的开发者社区!创建于2000年,历经19年的发展,受到业内的广泛认同,在行业中树立了令人尊敬的专业形象。平台为会员提供安全知识的在线课程教学,同时为企业提供智能设备安全相关产品和服务。
合作伙伴
上海纽盾科技股份有限公司( www.newdon.net )成立于2009年,是一家以“网络安全”为主轴,以“科技源自生活,纽盾服务社会”为核心经营理念,以网络安全产品的研发、生产、销售、售后服务与相关安全服务为一体的专业安全公司,致力于为数字化时代背景下的用户提供安全产品、安全服务以及等级保护等安全解决方案。
小手一戳,了解更多
公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com
戳原文,查看更多精彩writeup!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 小记一类ctf密码题解题思路
- WSDM Cup 2019 自然语言推理任务获奖解题思路
- 并发题的解题思路以及 Go 语言调度器工作原理
- 算法和编程面试题精选TOP50!(附代码+解题思路+答案)
- 看雪.纽盾 KCTF 2019 Q2 | 第一题点评及解题思路
- 看雪.纽盾 KCTF 2019 Q2 | 第三题点评及解题思路
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
高中数学公式定律及要点透析
牛胜玉 编 / 2011-2 / 9.80元
《PASS绿卡图书:高中数学公式定律及要点透析(人教A版)(必修+选修)(第9次修订)》精选例句:时尚鲜活例句,再现巩固单词;延伸拓展:搭配用法辨析,提升运用能力;真题例句:精选真题例句,紧密联系高考。便于携带:三年教材词汇,方便随时记忆;附赠录音:用耳朵记单词,让学习零空隙。一起来看看 《高中数学公式定律及要点透析》 这本书的介绍吧!