leftleftrightright(150)

这个题学到了不少东西,值得认真写一下

下载好文件后发现是upx的壳,upx -d直接脱掉后运行,发现是经典的check输入的题目(作为一个linuxer,首先用wine模拟运行了一下,这也为我后来的解题减少了不少麻烦,后边会说到)

ISCC2018_re150 [master●●] file leftleftrightright.exe
leftleftrightright.exe: PE32 executable (console) Intel 80386, for MS Windows, UPX compressed
ISCC2018_re150 [master●●] upx -d ./leftleftrightright.exe
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2013
UPX 3.91 Markus Oberhumer, Laszlo Molnar & John Reiser Sep 30th 2013 File size Ratio Format Name
-------------------- ------ ----------- -----------
18432 <- 10752 58.33% win32/pe leftleftrightright.exe Unpacked 1 file.
ISCC2018_re150 [master●●] file leftleftrightright.exe
leftleftrightright.exe: PE32 executable (console) Intel 80386, for MS Windows
ISCC2018_re150 [master●●] chmod +x leftleftrightright.exe
ISCC2018_re150 [master●●] ./leftleftrightright.exe
0009:fixme:msvcp:_Locinfo__Locinfo_ctor_cat_cstr (0x32fcbc 1 C) semi-stub
aaaaaaa
0009:fixme:msvcp:_Locinfo__Locinfo_ctor_cat_cstr (0x32fd1c 1 C) semi-stub
try again!
请按任意键继续...%

拖到IDA里分析之前,先搜索了一波字符串,发现存在IsDebuggerPresent和疑似加密后的flag:s_imsaplw_e_siishtnt{g_ialt}F,如果需要调试,要先nop掉IsDebuggerPresent,先静态分析,拖到IDA里F5大法,main函数的伪代码和汇编都很乱,但大致可以看出把我们的输入经过一通操作后扔给sub_401090()函数check,通过即为正确的flag,同时能看出flag的长度为29(0x1D)

  if ( sub_401090(v16) || v15 < 0x1D || (v17 = "flag is right!", v15 > 0x1D) )
v17 = "try again!";
v18 = sub_401BF0(std::cout, v17, sub_401E30);
std::basic_ostream<char,std::char_traits<char>>::operator<<(v18, v19);
system("pause");

这时首先想的是通过调试快速确定怎么对输入进行变化的,于是到windows下试图用Ollydbg调试(调试之前要先找到对IsDebuggerPresent的调用并nop掉,可以在IDA的import页面通过x交叉引用找到),这时遇到了第一个问题:文件在windows下直接crash



扔进OD单步调试,很快就能定位到crash出现的位置



crash出现的原因不难分析,此时[ds + 0x40600]是一个不可读的地址,这时候想起来windows vitia(writeup用的是windows 2008 server)及其以上版本引入了aslr技术,导致程序载入的基址是随机的,如果取值的地址是写死的(比如这道题),就很可能跳到不可读的地址,程序crash,细节可以看这里

一些trick:

  • OD把代码当成数据分析时,可以选中,点退格让OD重新分析
  • ctrl + A可以重新分析当前模块的代码,也能把误识别的数据转为代码

同时找到了一个很方便的工具可以固定程序的载入地址,固定程序的载入地址随机化后,打开程序,终于可以正常工作了,于是上OD调试,跟了几步指令后忽然意识到,check函数没有进行查表,亦或这些操作,只有很简单的位移,这说明我们的输入并不会发生改变,只会发生移位,如果我们能得到一串字符移位后的结果,就可以找到移位的规律,进而恢复出flag

//check函数不会改变输入
int __cdecl sub_401090(unsigned int a1)
{
int v1; // ecx
const char *v3; // esi
unsigned int v4; // edx
bool v5; // cf
unsigned __int8 v6; // al
unsigned __int8 v7; // al
unsigned __int8 v8; // al if ( !a1 )
return 0;
v3 = "s_imsaplw_e_siishtnt{g_ialt}F";
v4 = a1 - 4;
if ( a1 < 4 )
{
LABEL_6:
if ( v4 == -4 )
return 0;
}
else
{
while ( *(_DWORD *)v1 == *(_DWORD *)v3 )
{
v1 += 4;
v3 += 4;
v5 = v4 < 4;
v4 -= 4;
if ( v5 )
goto LABEL_6;
}
}
v5 = *(_BYTE *)v1 < (const unsigned __int8)*v3;
if ( *(_BYTE *)v1 != *v3 )
return -v5 | 1;
if ( v4 != -3 )
{
v6 = *(_BYTE *)(v1 + 1);
v5 = v6 < v3[1];
if ( v6 != v3[1] )
return -v5 | 1;
if ( v4 != -2 )
{
v7 = *(_BYTE *)(v1 + 2);
v5 = v7 < v3[2];
if ( v7 != v3[2] )
return -v5 | 1;
if ( v4 != -1 )
{
v8 = *(_BYTE *)(v1 + 3);
v5 = v8 < v3[3];
if ( v8 != v3[3] )
return -v5 | 1;
}
}
}
return 0;
}

于是我们直接在check函数之后下断点



运行,输入29位不同的数据后观察



找到了移位前后的字符串,这样就可以恢复flag了,脚本如下:

ISCC2018_re150 [master●●] cat solve.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__Auther__ = 'M4x' encrypt = "s_imsaplw_e_siishtnt{g_ialt}F" before = "abcdefghijklmnopqrstuvwxyzABC"
after = "onpqmlrskjtuihvwgfxyedzAcbBCa" flag = [encrypt[after.find(c)] for c in before]
print "".join(flag)
ISCC2018_re150 [master●●] python solve.py
Flag{this_was_simple_isnt_it}
ISCC2018_re150 [master●●]

以上是写writeup时偶然发现的新解法,新解法出现的原因应该是windows 2008 server的load机制与windows 10不同,windows 2008 server的更低级,原解法如下:

固定exe的装载基址后,发现运行到cin时,程序又crash了,这时才想到windows10下dll的装载基址也是随机的,通过比较aslr_disabler.exe处理前后的exe,发现只对pe头的一个字段改了一位(可以通过010 editor的compare功能看出),于是想到了两种思路:

  1. 找到exe调用的dll,通过修改pe头固定其基址
  2. 在od调试的过程中手动指定其基址

很明显第一种方法得不偿失,麻烦不说,很有可能造成系统环境的崩溃。于是尝试在OD调试的过程中指定dll的基址,试了一下发现要改的地方太多,放弃了。这个时候想到用wine模拟时程序可以正常运行,于是搜索了一下调试wine加载的程序的方法,google的所有结果都指向一个工具winedbg,按照man手册的说明,还可以以gdb模式启动,尝试了一下,发现在自己电脑上各种报错,把patch后的exe发给一个用arch的大佬学弟试了一下,一次就成了(吐血),比较后发现是wine的版本问题,于是果断卸载了apt安装的2.0的wine,手动编译了一个3.8的wine,然后winedbg --gdb ./leftleftrightright.exe,终于跑起来了,之后的方法就和使用ollydbg时一样了,直接下断点查看处理前后的字符串即可

patch后的exe和解题脚本可以在我的github上找到

一些补充:

  • 这道题目不难,但确实学到了不少东西,美中不足是把加密后的flag硬编码太弱了,根据题目名称leftleftrightright很容易猜出正确flag(我在编译wine时试了几次已经猜出了flag)
  • winedbg使用gdb模式启动时,如果使用pwndbg作为插件,会卡到怀疑人生,使用peda或者gef就会快得多(这也是大佬学弟告诉我的)
  • 刚开始也尝试过在windows vista以下的版本(如windows xp)上运行exe,但不兼容,搜索字符串可以看出这个程序是用vs2015编译的,搜索了一波发现除非重新编译,否则不能在exe上运行
  • 通过以上分析可以得出load的随机化程度 wine ≈ xp < windows 2008 server < win10,这也能看出微软在安全性上做了不少工作
  • 程序中还有一些0xcc(int 3),但分析过之后发现这些字节全在函数之间,不会被调用,因此对调试不会造成影响
    • 如果非要去除的话,可以参考如下idapython脚本,patch完记得保存(Edit -> Patch Program -> Apply Patches to Input File)

  • 对于一些细节,我还是没想明白,比如如何高效安全的固定dll的装载基质,IsDebuggerPresent在wine下为何失效(不patch此处的exe也可用winedbg调试),能否不重新编译使vs2015生成的exe兼容xp,为何从源码编译的wine会有下图中的报错以及如何解决(apt安装的2.0版wine没有如下报错)

  • 如果有师傅对以上问题以及这篇writeup有任何见解,欢迎指教

ISCC2018_leftleftrightright-Writeup的更多相关文章

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

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

  2. ISCC2016 WriteUp

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

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

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

  4. 爱春秋之戏说春秋 Writeup

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

  5. 《安全智库》:48H急速夺旗大战通关writeup(通关策略)

    作者:ByStudent   题目名字 题目分值 地址 MallBuilder2 350 mall.anquanbao.com.cn MallBuilder1 200 mall.anquanbao.c ...

  6. iscc2016 pwn部分writeup

    一.pwn1 简单的32位栈溢出,定位溢出点后即可写exp gdb-peda$ r Starting program: /usr/iscc/pwn1 C'mon pwn me : AAA%AAsAAB ...

  7. We Chall-Training: Encodings I -Writeup

    MarkdownPad Document html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,ab ...

  8. We Chall-Encodings: URL -Writeup

    MarkdownPad Document html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,ab ...

  9. We Chall-Training: ASCII—Writeup

    MarkdownPad Document html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,ab ...

  10. pwnable.kr-collision -Writeup

    bof html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,addres ...

随机推荐

  1. itest(爱测试) 4.4.0 发布,开源BUG 跟踪管理 & 敏捷测试管理软件

    itest 简介 test 开源敏捷测试管理,testOps 践行者.可按测试包分配测试用例执行,也可建测试迭代(含任务,测试包,BUG)来组织测试工作,也有测试环境管理,还有很常用的测试度量:对于发 ...

  2. 由于找不到opencv_world320d.dll,无法继续执行代码。解决方案

    将 opencv 安装路径 目录\opencv\build\x64\vc14\bin 中 3 个后缀是.dll 的应用程序扩展复制到 C:\Windows\System32 中 完美解决!

  3. layui弹出表单提交后,界面model验证部分起作用

    情况1----input属性中type=submit时验证都可以起作用,但是弹出层表单的返回值不能获取,所以用ajax二次提交后会出现重复添加数据的问题 情况2----input属性中type=but ...

  4. [ERR] Node goodsleep.vip:6379 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.

    解决方案 以前的cluster节点信息 保留 要删除 dump.rdb node.conf集群启动时自动生成文件

  5. CMS系统

    CMS是Content Management System的缩写,意为"内容管理系统" 对于内容管理,业界还没有一个统一的定义,不同的机构有不同的理解: 内容管理系统是企业信息化建 ...

  6. 第三章:使用ListView展示数据

    一.ImageList:存储图像集合 Images 存储的所有图像 ImageSize 图像的大小 ColorDepth 颜色数 TransparentColor 被视为透明的颜色 先设置ColorD ...

  7. 小白的java学习之路 “ 类和对象”

    一.※ 万物皆对象 二.对象的两个特征: 属性:对象具有的各种特征 方法:对象执行的操作 对象:用来描述客观事物的一个实体,由一组属性和方法构成 三.封装: 对象同时具有属性和方法两项特性 对象的属性 ...

  8. 解决苹果手机app store下载软件超过200M后必须使用wifi的终极方法(亲测有效)

      前言 最近使用苹果手机下载一款大小为300M左右的软件时弹出如下提示 因为平时主要使用wifi下载,偶尔用自己的流量也没有超过200M,所以用了这么久才发现苹果手机有这样一个限制. 这让我有些郁闷 ...

  9. gcc,g++,make,cmake的区别

    首先介绍一下GCC:GNU Compiler Collection(GNU 编译器集合),在为Linux开发应用程序时,绝大多数情况下使用的都是C语言,因此几乎每一位Linux程序员面临的首要问题都是 ...

  10. 使用xshell

    将选定的文本自动复制到剪贴板 并且 鼠标向右按钮定义为粘贴剪贴板内容