maze writeup

  攻防世界的一道迷宫题,第一次接触这样的题,个人感觉很有意思,收获也挺多,做一篇笔记记录一下。

程序分析

  1. __int64 sub_4006B0()
  2. {
  3. signed __int64 v0; // rbx
  4. signed int v1; // eax
  5. bool v2; // bp
  6. bool v3; // al
  7. const char *v4; // rdi
  8. __int64 v6; // [rsp+0h] [rbp-28h]
  9.  
  10. v6 = 0LL;
  11. puts("Input flag:");
  12. scanf("%s", &s1, 0LL);
  13. if ( strlen(&s1) != 24 || strncmp(&s1, "nctf{", 5uLL) || *(&byte_6010BF + 24) != 125 )// flag长度为24字节,前五个字节为"nctf{",最后一个字节要是"}"
  14. {
  15. LABEL_22:
  16. puts("Wrong flag!");
  17. exit(-1);
  18. }
  19. v0 = 5LL;
  20. if ( strlen(&s1) - 1 > 5 )
  21. {
  22. while ( 1 )
  23. {
  24. v1 = *(&s1 + v0); // 对每一位进行判断
  25. v2 = 0;
  26. if ( v1 > 78 )
  27. {
  28. v1 = (unsigned __int8)v1;
  29. if ( (unsigned __int8)v1 == 'O' ) // "O"表示向左移动
  30. {
  31. v3 = sub_400650((__int64)&v6 + 4);
  32. goto LABEL_14;
  33. }
  34. if ( v1 == 'o' ) // "o"表示向右移动
  35. {
  36. v3 = sub_400660((__int64)&v6 + 4);
  37. goto LABEL_14;
  38. }
  39. }
  40. else
  41. {
  42. v1 = (unsigned __int8)v1;
  43. if ( (unsigned __int8)v1 == '.' ) // "."表示向上移动
  44. {
  45. v3 = sub_400670((__int64)&v6);
  46. goto LABEL_14;
  47. }
  48. if ( v1 == '0' ) // "0"表示向下移动
  49. {
  50. v3 = sub_400680((__int64)&v6);
  51. LABEL_14:
  52. v2 = v3;
  53. goto LABEL_15;
  54. }
  55. }
  56. LABEL_15:
  57. if ( !(unsigned __int8)sub_400690((__int64)asc_601060, SHIDWORD(v6), v6) )// asc_601060是字符串首地址
  58. goto LABEL_22;
  59. if ( ++v0 >= strlen(&s1) - 1 )
  60. {
  61. if ( v2 )
  62. break;
  63. LABEL_20:
  64. v4 = "Wrong flag!";
  65. goto LABEL_21;
  66. }
  67. }
  68. }
  69. if ( asc_601060[8 * (signed int)v6 + SHIDWORD(v6)] != '#' )
  70. goto LABEL_20;
  71. v4 = "Congratulations!";
  72. LABEL_21:
  73. puts(v4);
  74. return 0LL;
  75. }

  主函数如上所示。我开始看的时候没有看明白,后来发现给出了四种操作符,对应上下左右四种移动,给出的字符串要想象成一个二维图像,相当于要用一个二维数组表示出来。

  flag的格式已经给我们规定好了:nctf{......}。

  1. __int64 __fastcall sub_400690(__int64 a1, int a2, int a3)
  2. {
  3. __int64 result; // rax
  4.  
  5. result = *(unsigned __int8 *)(a1 + a2 + 8LL * a3);
  6. LOBYTE(result) = (_DWORD)result == 32 || (_DWORD)result == 35;
  7. return result;
  8. }
  1. if ( !(unsigned __int8)sub_400690((__int64)asc_601060, SHIDWORD(v6), v6) )// asc_601060是字符串首地址
  2. goto LABEL_22;

  sub_400690函数这里拉出来看一下,SHIDWORD这里是一个宏定义,定义如下:

  1. #define SHIDWORD(x) (*((int32*)&(x)+1))

  对字符串如何取值或者对二级指针理解还不清楚的,可以尝试敲一下下面的测试代码:

  1. #include<stdio.h>
  2. #include<string.h>
  3.  
  4. int main()
  5. {
  6. __int64 v6;
  7. v6=1LL;char* a="abcdefghjk";
  8. printf("%p\n",a);
  9. printf("%p\n",*(&a));
  10. printf("%p\n",&a);
  11. printf("%c\n",*a);
  12. printf("%c",*(a+1));
  13. return 0;
  14. }

  宏定义和四种操作符理解不了,尝试下面的测试代码:

  1. #include<stdio.h>
  2. #include<string.h>
  3.  
  4. #define SHIDWORD(x) (*((__int32*)&(x)+1))
  5. int main()
  6. {
  7. __int64 v6;
  8. v6=1LL;
  9. char* a="abcdefghjk";
  10. printf("%p\n",&v6);
  11. printf("%p\n",(__int64)&v6);
  12. printf("%p\n",&v6+4);
  13. printf("%p\n",(__int64)&v6+4);
  14. printf("%p",&(SHIDWORD(v6)));
  15. return 0;
  16. }

  sub_400690中,v6是行数,即y坐标,SHIDWORD(v6)是列数,即x坐标,(__int64)asc_601060是字符串首地址。后面的判断表示走的时候,只能走“#”和空格。

  我们先把字符串转换成一个二维的迷宫

  1. maze=" ******* * **** * **** * *** *# *** *** *** *********"
  2. x=""
  3. New_maze=""
  4. for a in maze:
  5. if a==" ":
  6. New_maze+="0"
  7. elif a=="*":
  8. New_maze+="1"
  9. else:
  10. New_maze+=a
  11. x=""
  12. for i in range(len(New_maze)):
  13. x+=New_maze[i]
  14. if (i+1)%8==0:
  15. print(x)
  16. x=""

  然后从头开始,“O”表示向左移动,“o”表示向右移动,“.”表示向上移动,“0”表示向下移动(上下这里要注意,容易搞错)。四种操作符看不懂,就好好看一下上面给出的测试代码。

  最后得到flag:nctf{o0oo00O000oooo..OO}。

maze writeup的更多相关文章

  1. 【bugku】【ZSCTF】【迷宫RE】Take The Maze WriteUp

    Take The Maze 首先拿进PEID里查一下有没有壳: 无壳,果断拖进IDA.可是Graph View中找不到主程序的位置,在函数表里寻找主函数: 函数太多阻扰了我们找到主程序,运行一下程序找 ...

  2. Backtracking algorithm: rat in maze

    Sept. 10, 2015 Study again the back tracking algorithm using recursive solution, rat in maze, a clas ...

  3. 2016第七季极客大挑战Writeup

    第一次接触CTF,只会做杂项和一点点Web题--因为时间比较仓促,写的比较简略.以后再写下工具使用什么的. 纯新手,啥都不会.处于瑟瑟发抖的状态. 一.MISC 1.签到题 直接填入题目所给的SYC{ ...

  4. ISCC2016 WriteUp

    日期: 2016-05-01~ 注:隔了好久才发布这篇文章,还有两道Pwn的题没放,过一阵子放上.刚开始做这个题,后来恰巧赶上校内CTF比赛,就把重心放在了那个上面. 这是第一次做类似于CTF的题,在 ...

  5. (期望)A Dangerous Maze(Light OJ 1027)

    http://www.lightoj.com/volume_showproblem.php?problem=1027 You are in a maze; seeing n doors in fron ...

  6. 参加 Tokyo Westerns / MMA CTF 2nd 2016 经验与感悟 TWCTF 2016 WriteUp

    洒家近期参加了 Tokyo Westerns / MMA CTF 2nd 2016(TWCTF) 比赛,不得不说国际赛的玩法比国内赛更有玩头,有的题给洒家一种一看就知道怎么做,但是做出来还需要洒家拍一 ...

  7. 爱春秋之戏说春秋 Writeup

    爱春秋之戏说春秋 Writeup 第一关 图穷匕见 这一关关键是给了一个图片,将图片下载到本地后,打开以及查看属性均无任何发现,尝试把图片转换为.txt格式.在文本的最后发现这样一串有规律的代码: 形 ...

  8. 1204. Maze Traversal

    1204.   Maze Traversal A common problem in artificial intelligence is negotiation of a maze. A maze ...

  9. uva705--slash maze

    /*这道题我原本是将斜线迷宫扩大为原来的两倍,但是在这种情况下对于在斜的方向上的搜索会变的较容易出错,所以参考了别人的思路后将迷宫扩展为原来的3倍,这样就变成一般的迷宫问题了*/ #include&q ...

随机推荐

  1. POJ 3126 Prime Path 简单广搜(BFS)

    题意:一个四位数的质数,每次只能变换一个数字,而且变换后的数也要为质数.给出两个四位数的质数,输出第一个数变换为第二个数的最少步骤. 利用广搜就能很快解决问题了.还有一个要注意的地方,千位要大于0.例 ...

  2. Sublime3 markdown preview 修改输出的html页面默认宽度

    在sublime3 中安装了 Markdown Preview,Ctrl+B生成的HTML页面显示很窄,默认值为width: 45em,很多代码不能完整显示,需要拖动进度条,于是想要调整默认的宽度. ...

  3. Mybatis学习(7)实现mybatis分页

    上一篇文章里已经讲到了mybatis与spring MVC的集成,并且做了一个列表展示,显示出所有article 列表,但没有用到分页,在实际的项目中,分页是肯定需要的.而且是物理分页,不是内存分页. ...

  4. mysql被收购 用mariadb (转)

    ~]# systemctl start mysql.service 要启动MySQL数据库是却是这样的提示 Failed to start mysqld.service: Unit not found ...

  5. ctf实验吧Once More

    题目链接:http://ctf5.shiyanbar.com/web/more.php 思路分析:显然是后台逻辑代码. 1.ereg函数有漏洞,可以使用%00截断,这个就做笔记了好吧.这个函数大致意思 ...

  6. SpringBoot缓存管理(三) 自定义Redis缓存序列化机制

    前言 在上一篇文章中,我们完成了SpringBoot整合Redis进行数据缓存管理的工作,但缓存管理的实体类数据使用的是JDK序列化方式(如下图所示),不便于使用可视化管理工具进行查看和管理. 接下来 ...

  7. C语言:宏定义

    #include <stdio.h> #define PI 3.14159265454454235432453245 main() { printf("%f\n",PI ...

  8. VMware workstation虚拟机配置文件不兼容无法使用解决方法

    VMware workstation虚拟机配置文件不兼容无法使用解决方法打开VMware workstation虚拟机提示:配置文件"--.vmx"是由Vmware产品创建,但该产 ...

  9. c语言字符串占据字节数

    # include <stdio.h> //字符串占据的字节数 /* 不能将一个字符串常量赋给一个字符变量 为什么不能将一个字符串常量赋给一个字符变量?可以从两个方面作出解释: 前面讲过, ...

  10. 开源桌面快速启动工具-GeekDesk

    GeekDesk 小巧.美观的桌面快速启动工具 开发框架 wpf .net 4.7.2 HandyControl 全局热键 鼠标跟随 快速启动 随时随地 支持自定义热键 支持鼠标跟随 自定义壁纸 随意 ...