第五题《交响曲》的攻击时间在今天(12月11日)中午12:00结束,意味着KCTF此次攻击赛势已经走过了三分之一的进程。

tekkens团队!3353s夺得本题第一名!

成功攻击第五题《交响曲》的团队此次也创下赛事小高峰,共计31支团队。

最新赛况战况一览

比赛到1/3进程后的新排名是什么样的呢?我们一起来看一下。

我们可以发现,第一名到第四名的团队和上一场总排名保持一致,而第五名到第六名则全部变动。那么,前四名能在后面的比赛继续守擂成功吗?又会有新的黑马团队杀出来搅乱整个局势吗?我们拭目以待!

第五题 点评

crownless:

交响曲这道题是一道安卓逆向分析题,采用了称骨算命的算法设计。题目要求参赛者通过“命运值”反推出“生辰八字”,因此需要在理解算法的基础上通过编写脚本来破解“生辰八字”,饶有趣味。

第五题 出题团队简介

出题团队: 妳的名稱過長  

第五题 设计思路

由看雪论坛 KwaiChing 原创

0x00. 注册码: 1995020305to07

0x01. 思路:

程序根据称骨算命的算法设计, 以3.4两的命运反推出生日期(农历), 并排除一九九五年二月初三之外相同出生日期

0x02. 称骨算命:

出生 年 月 日 时 八字对应不同骨重:

int[] yearWeightArray = { 7, 7, 9, 12, 8, 7, 13, 5, 14, 5, 9, 17, 5, 7, 12, 8, 8, 6, 19, 6, 8, 16, 10, 6, 12, 9, 6, 7, 12, 5, 9, 8, 7, 8, 15, 9, 16, 8, 8, 19, 12, 6, 8, 7, 5, 15, 6, 16, 15, 7, 9, 12, 10, 7, 15, 6, 5, 14, 14, 9 };

int[] monthWeightArray = { 6, 7, 18, 9, 5, 16, 9, 15, 18, 8, 9, 5 };

int[] dayWeightArray = { 5, 10, 8, 15, 16, 15, 8, 16, 8, 16, 9, 17, 8, 17, 10, 8, 9, 18, 5, 15, 10, 9, 8, 9, 15, 18, 7, 8, 16, 6 };

   int[] hourWeightArray = { 16, 6, 7, 10, 9, 16, 10, 8, 8, 9, 6, 6 };

骨重相加之和对应不同命运(见附件)

0x03. 注册码就是出生年+月+日+时

年份限制在1983-2007之间

getTempDate():

if ((this.tempY <= 1983) || (this.tempY >= 2007)) {

this.tempY = 0;

}

其中各时刻:

  • 子(23:00~01:00)

  • 丑(01:00~03:00)

  • 寅(03:00~05:00)

  • 卯(05:00~07:00)

  • 辰(07:00~09:00)

  • 巳(09:00~11:00)

  • 午(11:00~13:00)

  • 未(13:00~15:00)

  • 申(15:00~17:00)

  • 酉(17:00~19:00)

  • 戌(19:00~21:00)

  • 亥(21:00~23:00)

以字符串替代:

String[] hour = {

"23to01",

"01to03",

"03to05",

"05to07",

"07to09",

"09to11",

"11to13",

"13to15",

"15to17",

"17to19",

"19to21",

"21to23"}

0x04.getLunar函数排除符合结果中除特定年份和月份之外的注册码

if ((this.tempY == 1989) || (this.tempY == 2004)) {

               this.tempD = 31; // 排除1989 和2004年

           }

// 排除特定月份

           if ((this.tempM == 1) || (this.tempM == 4) || (this.tempM ==5) || (this.tempM ==7) || (this.tempM ==10) || (this.tempM ==11) || (this.tempM ==12)) {

               this.tempY = 1999; // 排除特定月份 注:1999年没有3.4两的骨重

           }

           if ((this.tempY <= 1994) && ((this.tempM == 2) ||(this.tempM == 6) || (this.tempM == 8))) {

               this.tempM = 3; // 除1989和2004外 其他年份3月没有3.4两骨重

           }

           if ((this.tempY >= 1996) && ((this.tempM == 2) ||(this.tempM == 6) || (this.tempM == 8))){

               this.tempM = 9; // 除1989和2004外 其他年份9月没有3.4两骨重

           }

           if ((this.tempY == 1995) && ((this.tempD > (this.tempM + 2)) || this.tempM == this.tempD )){

               this.tempM = 6; // 1995年9月没有3.4两骨重

           }

0x05. getHourWeight()函数中亦排除二月份卯时出生的八字:

if ((j == 2) && tempH.equals(hour[6])){

return 63; // 6.3两的时骨重和其他骨重(0.5*3=1.5, )相加超出骨重值7.2钱

}

0x06. 相关称骨计算详情见附件FateMe源码

原文链接:

https://bbs.pediy.com/thread-228479.htm(含附件)

第五题 交响曲 解题思路

本题解析由看雪论坛 顾言庭 原创。

环境配置

  • 系统 : Windows 7、nexus 5

  • 程序 : CrackMe.KwaiChing.apk

  • 要求 : 输入口令

  • 使用工具 : 称骨算命、Android Studio、jadx、apktool

搜集线索

在测试机中安装该apk,发现程序需求一个key,如果以123这样的随机数作为输入的话,会输出failed!!!

我们使用apktool反编译这个程序:

apktool d CrackMe.KwaiChing.apk

然后在\res\values\strings.xml位置查看字符串信息:

<string name="me">"s \u0009\u0009u \u0009\u0009\u0009c \u0009\u0009\u0009\u0009c \u0009\u0009\u0009\u0009\u0009e \u0009\u0009\u0009\u0009\u0009\u0009s \u0009\u0009\u0009\u0009\u0009\u0009\u0009s \u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009! \u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009!

"</string>   <string name="notMe">f \u0009a \u0009\u0009i \u0009\u0009\u0009l \u0009\u0009\u0009\u0009e \u0009\u0009\u0009\u0009\u0009d \u0009\u0009\u0009\u0009\u0009\u0009! \u0009\u0009\u0009\u0009\u0009\u0009\u0009! \u0009\u0009\u0009\u0009\u0009\u0009\u0009\u0009!</string>   <string name="ok">驗證</string>   <string name="search_menu_title">Search</string>   <string name="status_bar_notification_info_overflow">999+</string>   <string name="success00" />   <string name="success34">"財穀有餘主得內助富貴之命

此命福氣果如何,僧道門中衣祿多;離祖出家方為妙,朝晚拜佛念彌陀。

此命推來為人性躁;與人做事反為不美;離祖成家;三番四次自成自立安享福;直自三十六至四十六;財不謀而自至;福不求而自得;有貴人助;家庭安寧;妻宮若要無刑;猴、豬、羊、蛇不可配;龍、虎、馬、牛方得安;雖有二子;終生帶暗方可.兄弟六親如冰碳;在家不得安然;初限駁雜多端;勞碌奔波不能聚錢;常有憂愁.壽元七十八歲;死於三月中."</string>

看来存在有一个提示正确和一个提示错误的字符串,还有就是success34的迷之字符串。我搜索了一下,居然发现了存有相关信息的网页。

看来是一个玄学题目(笑。

开始分析

我们运行jadx:

D:\software\jadx-0.8.0(1)\lib>java -jar jadx-gui-0.8.0.jar

定位到p007cn.kwaiching.crackme包下的CrackMe类,发现这就是算法的主流程:

protected void onCreate(Bundle bundle) {   super.onCreate(bundle);   setContentView((int) R.layout.activity_fate_me);   b();   this.n = (TextView) findViewById(R.id.fate);   ((Button) findViewById(R.id.ok)).setOnClickListener(new OnClickListener() {       public void onClick(View view) {           try {               CrackMe.this.a();           } catch (Exception unused) {               CrackMe.this.n.setText(CrackMe.this.getString(R.string.notMe));           }       }   });}

来看看a的流程:

private void a() {   try {       c();       if (this.j == 0 || this.i == 0 || this.h == 0) {           this.n.setText(getString(R.string.notMe));           return;       }       d();       a(((e() + f()) + g()) + h());   } catch (Exception unused) {       this.n.setText(getString(R.string.notMe));   }}

我们先来查看h函数的部分代码:

/* JADX WARNING: Removed duplicated region for block: B:17:0x0050 A:{Catch:{ Exception -> 0x005c }} */private int h() {    /*    r6 = this;    r0 = 2131165227; // 0x7f07002b float:1.7944665E38 double:1.0529355243E-314;    r1 = 2131427370; // 0x7f0b002a float:1.8476354E38 double:1.05306504E-314;    r2 = 0;    r0 = r6.findViewById(r0);     Catch:{ Exception -> 0x005c }

这样的代码就是jadx的反编译出了点问题,我们需要设置一下选项,让代码的可读性变高。

代码修饰

这里,在jadx的菜单中点击文件->设置->启用反混淆,接着选择
显示不一致的代码。这时,可以发现代码漂亮了不少。

导入as查看

在jadx中查看,不如导入到android stdio(下文中简称为as)这样专业的ide中查看,这样能修改变量名,快速查看引用位置等等。

这里,在jadx的菜单中点击文件->另存为 gradle项目,选中一个任意一个空的文件夹,然后保存就可以。

流程分析

在as中,发现主流程是:

private void m162a() {

    try {

        m166c();

        if (this.year == 0 || this.month == 0 || this.day == 0) {

            this.f125n.setText(getString(C0252R.string.notMe));

            return;

        }

        m167d();

        m163a(((m168e() + m169f()) + m170g()) + m171h());

    } catch (Exception unused) {

        this.f125n.setText(getString(C0252R.string.notMe));

    }

}

m166c函数的流程是:

/* renamed from: c */

private void m166c() {

    try {

        String obj = ((EditText) findViewById(C0252R.id.code)).getText().toString();

        this.year = 0;

        this.month = 0;

        this.day = 0;

        this.year = Integer.parseInt(obj.length() > 4 ? obj.substring(0, 4) : obj);

        if (this.year > 0 && this.year < 189) {

            this.year = 0;

        }

        if (this.year <= 1983 || this.year >= 2007) {

            this.year = 0;

        }

        this.month = Integer.parseInt(obj.length() > 6 ? obj.substring(4, 6) : obj);

        if (this.month < 1 || this.month > 12) {

            this.month = 0;

        }

        if (obj.length() > 8) {

            obj = obj.substring(6, 8);

        }

        this.day = Integer.parseInt(obj);

        if (this.day < 1 || this.day > 31) {

            this.day = 0;

        }

    } catch (Exception unused) {

        this.f125n.setText(getString(C0252R.string.notMe));

    }

}

稍微分析一下,可知程序把输入限定在:

  1. 年份:1983后,2007前。

  2. 月份:1-12

  3. 日期:1-31

再来看看其他的函数:

private void m167d() {

    try {

        if (this.year == 1989 || this.year == 2004) {

            this.day = 31;

        }

        if (this.month == 1 || this.month == 4 || this.month == 5 || this.month == 7 || this.month == 10 || this.month == 11 || this.month == 12) {

            this.year = 1999;

        }

        if (this.year <= 1994 && (this.month == 2 || this.month == 6 || this.month == 8)) {

            this.month = 3;

        }

        if (this.year >= 1996 && (this.month == 2 || this.month == 6 || this.month == 8)) {

            this.month = 9;

        }

        if (this.year == 1995 && (this.day > this.month + 2 || this.month == this.day)) {

            this.month = 6;

        }

        this.my_year = this.year;

        this.my_month = this.month;

        this.my_day = this.day;

    } catch (Exception unused) {

        this.f125n.setText(getString(C0252R.string.notMe));

    }

}

这里其实是将可能的输入范围减少了,比如第一个判断,2004和1989年的所有可选日期都是31号。以此类推。

四个小函数

private int m168e() {

        try {

            return this.f115d[(this.my_year - 1900) % 60];

        } catch (Exception unused) {

            this.f125n.setText(getString(C0252R.string.notMe));

            return 0;

        }

    }

    /* renamed from: f */

    private int m169f() {

        try {

            return this.f114c[this.my_month - 1];

        } catch (Exception unused) {

            this.f125n.setText(getString(C0252R.string.notMe));

            return 0;

        }

    }

    /* renamed from: g */

    private int m170g() {

        try {

            return this.f113b[this.my_day - 1];

        } catch (Exception unused) {

            this.f125n.setText(getString(C0252R.string.notMe));

            return 0;

        }

    }

    /* JADX WARNING: Removed duplicated region for block: B:17:0x0050 A:{Catch:{ Exception -> 0x005c }} */

    /* Code decompiled incorrectly, please refer to instructions dump. */

    /* renamed from: h */

    private int m171h() {

        try {

            Object obj;

            String other_str = ((EditText) findViewById(C0252R.id.code)).getText().toString();

            other_str = other_str.substring(8, other_str.length());

            int MONTH = this.my_month;

            int i2 = 0;

            while (i2 < this.f124m.length) {

                if (!other_str.equals(this.f124m[i2])) {

                    i2++;

                } else if (MONTH == 2 && other_str.equals(this.f124m[6])) {

                    return 63;

                } else {

                    this.f122k = this.f112a[i2];

                    obj = 1;

                    if (obj == null) {

                        this.f125n.setText(getString(C0252R.string.notMe));

                    }

                    return this.f122k;

                }

            }

            obj = null;

            if (obj == null) {

            }

            return this.f122k;

        } catch (Exception unused) {

            this.f125n.setText(getString(C0252R.string.notMe));

            return 0;

        }

    }

}

最本质的操作都是从固定数组中取值,然后返回相关值。以下是相关数组:

/* renamed from: a */

int[] f112a = new int[]{16, 6, 7, 10, 9, 16, 10, 8, 8, 9, 6, 6};

/* renamed from: b */

int[] f113b = new int[]{5, 10, 8, 15, 16, 15, 8, 16, 8, 16, 9, 17, 8, 17, 10, 8, 9, 18, 5, 15, 10, 9, 8, 9, 15, 18, 7, 8, 16, 6};

/* renamed from: c */

int[] f114c = new int[]{6, 7, 18, 9, 5, 16, 9, 15, 18, 8, 9, 5};

/* renamed from: d */

int[] f115d = new int[]{7, 7, 9, 12, 8, 7, 13, 5, 14, 5, 9, 17, 5, 7, 12, 8, 8, 6, 19, 6, 8, 16, 10, 6, 12, 9, 6, 7, 12, 5, 9, 8, 7, 8, 15, 9, 16, 8, 8, 19, 12, 6, 8, 7, 5, 15, 6, 16, 15, 7, 9, 12, 10, 7, 15, 6, 5, 14, 14, 9};

String[] f124m = new String[]{"23to01", "01to03", "03to0

判断函数

这个判断函数,emmm...

private void m163a(int i) {    if (i > 34 || i < 34) {        this.f125n.setText(getString(C0252R.string.notMe));        return;    }    try {        this.f125n.setText(String.format("%s%s", new Object[]{getString(C0252R.string.me), this.f123l[i]}));        ((Button) findViewById(C0252R.id.ok)).setEnabled(false);    } catch (Exception unused) {        this.f125n.setText(getString(C0252R.string.notMe));    }}

可知需求i值为34了。

逻辑推理

我们知道,作者需求我们输入生辰八字,如果生辰八字按某种特定方式取值相加的结果为34,那么夺旗成功。

计算一下遍历所有可能的计算次数:

2007-1983=2424 * 12 * 31 * 12 = 107136

十万次的运算对于计算机来说不算什么,如果发现可能的结果太多,再添加m167d函数中的判断缩小取值范围,还有m171h函数中的这一句:

MONTH == 2 && other_str.equals(this.f124m[6])

其实表示,月份为2时,时辰索引值不能取6,否则失败。

编写代码

根据以上逻辑,我们做python代码如下:

hour_weight_list = [16, 6, 7, 10, 9, 16, 10, 8, 8, 9, 6, 6]day_weight_list = [5, 10, 8, 15, 16, 15, 8, 16, 8, 16, 9, 17, 8, 17, 10, 8, 9, 18, 5, 15, 10, 9, 8, 9, 15, 18, 7, 8, 16, 6]month_weight_list = [6, 7, 18, 9, 5, 16, 9, 15, 18, 8, 9, 5]# begin at 1960year_weight_list = [7, 7, 9, 12, 8, 7, 13, 5, 14, 5, 9, 17, 5, 7, 12, 8, 8, 6, 19, 6, 8, 16, 10, 6, 12, 9, 6, 7, 12, 5, 9, 8, 7, 8, 15, 9, 16, 8, 8, 19, 12, 6, 8, 7, 5, 15, 6, 16, 15, 7, 9, 12, 10, 7, 15, 6, 5, 14, 14, 9]

date_list = []for year_index in range(1984,2007):    for month_index in range(1,len(month_weight_list)+1):        for day_index in range(1,len(day_weight_list)+1):            for hour_index in range(0,len(hour_weight_list)):                year_weight = year_weight_list[(year_index - 1900) % 60]                month_weight = month_weight_list[month_index-1]                day_weight = day_weight_list[day_index-1]                hour_weight = hour_weight_list[hour_index]

                year = year_index                month = month_index                if year == 1989 or year == 2004:                    continue                if month == 1 or month == 4 or month == 5 or month == 7 or month == 10 or month == 11 or month == 12:                    year = 1999                    year_weight = year_weight_list[(year - 1900) % 60]                if year <= 1994 and (month == 2 or month == 6 or month == 8):                    month = 3                    month_weight = month_weight_list[month-1]                if year >= 1996 and (month == 2 or month == 6 or month == 8):                    month = 9                    month_weight = month_weight_list[month-1]                if year == 1995 and (day_index > month + 2 or month == day_index):                    month = 6                    month_weight = month_weight_list[month-1]

                if ( year_weight + month_weight + day_weight + hour_weight ) == 34:                    date = str(year_index) + '/' + str(month_index) + '/' + str(day_index) + '/' + str(hour_index)                    if date_list.count(date) == 0:                        date_list.append(date)

print "find_times = " + str(len(date_list))print date_list[0]print date_list[1]

夺旗成功

最终运算结果如下:

➜  play_ground python count_date.pyfind_times = 21995/2/3/31995/2/3/6

根据月份为2,索引值不能为6的推论,我们得到了唯一的flag1995020305to07,输入flag,程序提示成功,并弹出一段迷之算命结果。

95年的小伙,和我同龄,还不错的。不过,果然还是少看些算命,好好学习,天天向上比较好哦。

参考

1、Android 反编译神器jadx的使用


文章链接如下:

https://blog.csdn.net/Fisher_3/article/details/78654450

WP原文链接:

https://bbs.pediy.com/thread-248308.htm

第六题【追凶者也】正在火热进行中

第6题/共15题

《追凶者也》将于12月13日中午12:00结束

赶紧参与进来吧~!

合作伙伴

腾讯安全应急响应中心 

TSRC,腾讯安全的先头兵,肩负腾讯公司安全漏洞、黑客入侵的发现和处理工作。这是个没有硝烟的战场,我们与两万多名安全专家并肩而行,捍卫全球亿万用户的信息、财产安全。一直以来,我们怀揣感恩之心,努力构建开放的TSRC交流平台,回馈安全社区。未来,我们将继续携手安全行业精英,探索互联网安全新方向,建设互联网生态安全,共铸“互联网+”新时代。

- End -

公众号ID:ikanxue

官方微博:看雪安全

商务合作:wsc@kanxue.com

看雪CTF.TSRC 2018 团队赛 第五题 『交响曲』 解题思路相关推荐

  1. 看雪ctf 流浪者 WP

    看雪ctf 第一题 流浪者 wp   打开程序,提示要验证password,载入OD,按照签到题的思路,改了一个跳转,出现了提示框pass,但是没有flag,应该不是这种思路(我是一个刚入手的萌新,可 ...

  2. 看雪CTF 2016_第八题分析

    用exeinfo查看发现是x64程序,所以用平常的OD调试器是调试不到的,需要用x64的调试器 我这里是用x64dbug 这个调试器来进行调试分析 经过一步一步调试,发现程序调用RtlMoveMemo ...

  3. 看雪CTF 2016_第四题分析

    结合前辈们的分析,自己再作一个分析,算是当做学习笔记吧! OD 下GetDlgItemTextA 这个断点 0040148C |. 83F8 1E cmp eax,0x1E 检测注册码长度是否为30位 ...

  4. 2015年第六届蓝桥杯C/C++ A组国赛 —— 第五题:切开字符串

    标题:切开字符串 Pear有一个字符串,不过他希望把它切成两段. 这是一个长度为N(<=10^5)的字符串. Pear希望选择一个位置,把字符串不重复不遗漏地切成两段,长度分别是t和N-t(这两 ...

  5. 2013年第四届蓝桥杯C/C++ A组国赛 —— 第五题:网络寻路

    标题:网络寻路 X 国的一个网络使用若干条线路连接若干个节点.节点间的通信是双向的.某重要数据包,为了安全起见,必须恰好被转发两次到达目的地.该包可能在任意一个节点产生,我们需要知道该网络中一共有多少 ...

  6. HDU 4292 Food (成都赛区网络赛第五题,拆点网络流)

      题意:跟POJ3281基本上一样的拆点网络流. 建图:建一超级源点和一超级汇点,源点与食物相连,边权为其数量,汇点与饮料相连,边权也为其数量,把人分成两个点,之间的边权为1.每个人与之需要的食物和 ...

  7. 第十二届蓝桥杯省赛A组砝码称重Java解题思路及代码

    [问题描述] 你有一架天平和 N个砝码,这N个砝码重量依次是W1, W2, -, Wn. 请你计算一共可以称出多少种不同的重量?注意砝码可以放在天平两边. [输入格式] 输入的第一行包含一个整数N. ...

  8. php-5.3.3.tat.gz,[JS逆向 JS混淆] 猿人学 爬虫攻防赛 第五题

    [JavaScript] 纯文本查看 复制代码var _$8K = {}; var _$ev = [], _$Uy = String.fromCharCode; function _$HY(_$5X) ...

  9. 2017年第八届蓝桥杯 JavaB组国赛 第五题 填字母游戏

    标题:填字母游戏 小明经常玩 LOL 游戏上瘾,一次他想挑战K大师,不料K大师说: "我们先来玩个空格填字母的游戏,要是你不能赢我,就再别玩LOL了". K大师在纸上画了一行n个格 ...

  10. CET-6 | 2018年 六级真题『翻译』语句

    be open to - free of charge / for free | 免费向-开放 - has seen an obvious increase / has increased signi ...

最新文章

  1. Mybatis-plus多表关联查询,多表分页查询
  2. 【转】 Android新特性介绍,ConstraintLayout完全解析
  3. Elastic Search 上市了,Slack上市了,我也要写个软件,走上人生巅峰
  4. worker进程和task进程区别_celery 每个 worker 在执行任务时,如何配置一定数量的 task?...
  5. 机器学习实践:本地远程查看服务器训练TensorBoard
  6. 44 个 JavaScript 变态题解析
  7. (轉貼) ThinkPad鍵盤設計原理和哲學 (NB) (ThinkPad)
  8. CodeForces 1361E James and the Chase(dfs + 结论)
  9. TCP/IP 三次握手
  10. PostgreSQL与MySQL的日期类型DATE/date的格式区别
  11. 和公婆住在一起是什么体验?
  12. 中琅领跑条码打印软件如何导入CDR文件
  13. 使用Stream生成菜单、地区树
  14. 京东自动抢购茅台脚本
  15. Android免费地图应用网址
  16. KUBERNETES安装及访问web页面
  17. R语言字符串相关操作
  18. 微信网页扫码支付(公众号)JAVA实现
  19. tp5用redis防高并发
  20. 记一次UDP接入服务的性能测试

热门文章

  1. Oracle-SQL程序优化4
  2. Comparable接口
  3. 微信商户平台的“企业付款到用户” 产品功能被隐藏起来了。。
  4. office如何去除多页签
  5. iOS网络请求下来的数据显示时出现的问题
  6. Arturia Prophet V3 for Mac(多功能仿真音乐合成器)
  7. Sound Grinder Pro for Mac(音频批量编辑转换工具)
  8. iOS底层探索之多线程(二)—线程和锁
  9. WebSocket:5分钟从入门到精通
  10. 运用思维导图学习数据分析的五个步骤