0x01 arguement

下载链接:https://www.lanzous.com/i7atyhc

1.准备

获取到信息:

  1. 32位的文件
  2. upx加密文件

在控制台打开文件

使用"upx -d reverse.exe"解密

2.IDA打开

直接在String中,找到引用"Input Your Flag:"的位置

int __usercall sub_415280@<eax>(int xmm0_4_0@<xmm0>, int a1, int a2)
{
int v3; // edx
FILE *v4; // eax
int v5; // edx
int v6; // ecx
char *v7; // eax
int v8; // edx
int v9; // ecx
int v10; // ST04_4
int v11; // ST08_4
char v13; // [esp+0h] [ebp-134h]
char Buf; // [esp+D0h] [ebp-64h]
size_t i; // [esp+100h] [ebp-34h]
FILE *File; // [esp+10Ch] [ebp-28h]
char v17; // [esp+118h] [ebp-1Ch]
int v18; // [esp+130h] [ebp-4h]
int savedregs; // [esp+134h] [ebp+0h] sub_411208((int)&unk_41C008);
printf("Input Your Flag:\n", v13);
sub_41137F("%19s", (unsigned int)&v17); // v12大小为24
if ( a1 != )
{
printf("Input error!\n", v13);
exit();
}
printf("%s\n", *(_DWORD *)(a2 + )); // 在执行文件时,执行的第一个参数
for ( i = ; i < j_strlen(*(const char **)(a2 + )); ++i )// 遍历执行文件时输入的字符串
*(_BYTE *)(*(_DWORD *)(a2 + ) + i) += i; // 每一位 str[i] += i
if ( !j_strcmp(Str1, *(const char **)(a2 + )) )// 和“fmcj2y~{”比较
{
v4 = fopen(*(const char **)(a2 + ), "r"); // 下面两句文件操作,应该是获取输入的
File = (FILE *)sub_411212(v6, v5, &v13 == &v13, (int)v4, xmm0_4_0);
if ( File )
{
v7 = fgets(&Buf, , File);
sub_411212(v9, v8, &v13 == &v13, (int)v7, xmm0_4_0);
if ( j_strlen(&Buf) != || j_strlen(&Buf) % == )// 输入长度应该是32
exit();
sub_4113B1(xmm0_4_0, &Buf, (int)&unk_41A4E0);
if ( sub_4113B6(xmm0_4_0, (int)&unk_41A4E0) )
printf("flag{%s}", (unsigned int)&Buf);
else
printf("Input Error!\n", v13);
}
else
{
printf("Input Error!\n", v13);
}
}
else
{
printf("Input Error!\n", v13);
}
sub_411235(&savedregs, dword_4154C4, , v3);
return sub_411212((unsigned int)&savedregs ^ v18, v11, , v10, xmm0_4_0);
}

因此在运行时文件我们要在后面带一个参数,这个参数通过分析代码,我们可以写个脚本解出

str1 = 'fmcj2y~{'

str2 = ''

for i in range(len(str1)):
str2 += chr(ord(str1[i]) - i) print (str2

3.代码分析

通过分析,可以知道关键的函数是sub_4113B1sub_4113B6

3.1 sub_4113B1函数

int __usercall sub_414E50@<eax>(int a1@<xmm0>, char *Str, int a3)
{
unsigned int v3; // eax
int v4; // edx
int v5; // ecx
char v7; // [esp+0h] [ebp-E4h]
int v8; // [esp+D0h] [ebp-14h]
signed int i; // [esp+DCh] [ebp-8h] sub_411208((int)&unk_41C008);
dword_41A078[] = 0xA7;
dword_41A078[] = 0xDE;
dword_41A078[] = 0xDA;
dword_41A078[] = 0x46;
dword_41A078[] = 0xAB;
dword_41A078[] = 0x2E;
dword_41A078[] = 0xFF;
dword_41A078[] = 0xDB;
for ( i = ; ; i += ) // 0开始,2跳
{
v3 = j_strlen(Str); // v3为Buf长度32
if ( i >= v3 )
break;
if ( Str[i] >= && Str[i] <= ) // '0'~'9'
{
*(_DWORD *)(a3 + * (i / )) = Str[i] - ;// 字符转换为整型
}
else
{
if ( Str[i] < || Str[i] > ) // 非'a'~'f',说明组成的字符是'0'~'9'||'a'~'f',十六进制啊
{
printf("Input Error!\n", v7);
exit();
}
*(_DWORD *)(a3 + * (i / )) = Str[i] - ;// 十六进制啊!'a'~'f'就是10~15
}
*(_DWORD *)(a3 + * (i / )) *= ; // 最后还要乘16
if ( Str[i + ] >= && Str[i + ] <= ) // i=1,3,5...如果为数字
{
v8 = Str[i + ] - ; // v8=字符转数字
}
else
{
if ( Str[i + ] < || Str[i + ] > )
{
printf("Input Error!\n", v7);
exit();
}
v8 = Str[i + ] - ; // i=1,3,5...如果是'a'~'f'字符转数字,10~15
}
*(_DWORD *)(a3 + * (i / )) += v8; // a3[i]+=v8
}
return sub_411212(v5, v4, , v3, a1);
}

这个函数有两个作用:

  1. 对dword_41A078后8双字节赋值
  2. 将输入的字符串,两两字符转换为数字,存入v4,例如:输入"a1b2c3"将会转换为0xa1b2c3

3.2 sub_4113B6函数

int __usercall sub_411D90@<eax>(int a1@<xmm0>, int a2)
{
int v2; // edx
int v3; // ecx
int v4; // eax
signed int i; // [esp+D0h] [ebp-8h] sub_411208((int)&unk_41C008);
for ( i = ; i < ; ++i )
{
v3 = a2; // v3赋值为之前得到的整数
v2 = *(_DWORD *)(a2 + * i) + ; // v2=v2[i]+1
if ( v2 != dword_41A078[i] )
{
v4 = ;
return sub_411212(v3, v2, , v4, a1);
}
}
v4 = ;
return sub_411212(v3, v2, , v4, a1);
}

这个函数将我们转换输入字符串得到的v4。每一位加1之后与已知的dword_41A078数组比较。

dword_41A078

50h 0C6h 0F1h 0E4h 0E3h 0E2h 9Ah 0A1h 0A7h 0DEh 0DAh 46h 0ABh 2Eh 0FFh 0DBh

因此我们只要将dword_41A078每一位减1,就能得到v4,从而输入的Buf也得到了了

v4

4fc5f0e3e2e199a0a6ddd945aa2dfeda

Buf

"4fc5f0e3e2e199a0a6ddd945aa2dfeda"

而回到主函数

if ( sub_4113B6(xmm0_4_0, (int)&unk_41A4E0) )
printf("flag{%s}", (unsigned int)&Buf);

flag就是flag{Buf}

4.get flag!

flag{4fc5f0e3e2e199a0a6ddd945aa2dfeda}

0x02 EzRE

下载链接:https://www.lanzous.com/i7atzwd

原题:

https://www.jianshu.com/p/7fdfe2333123

http://www.pianshen.com/article/8985544588/

flag{#FFRFFF####ZZRZZZ##FF#FFFF}

0x03 icekey

下载链接:https://www.lanzous.com/i7atzwd

使用dnSpy打开之后,找到main函数打开

这通过观察反编译的C#代码,能够知道这段代码就是将我们输入的字符串经过加密后,与b="3ACF8D62AAA0B630C4AF43AF327CE129D46F0FEB98D9040F713BE65502A5107A"比较,相同则返回true否则返回false。

并且这段代码还很贴心的在下面写出了解密函数,因此只需要在我们调试中,输入字符串并加密后,将调试窗口处的array数组和bytes数组改为与b数组相等即可(因为在加密和比较中用到了这两个数组)

最终,调试至程序结束,我们能够在内存窗口追踪到bytes解密后的字符数组,即为我们正确的输入:

5acb06231724c8c369bae711166dbe85

0x04 android

下载链接:https://www.lanzous.com/i7au7pe

2019中国杭州网络安全技能大赛 预选赛原题,不过没解完。

https://xhyeax.github.io/2019/04/07/2019-hzwas-wp/

0x05 总结

湖湘杯又被吐槽了...Reverse基本都是签到题,菜鸡做着还是舒服。

2019 湖湘杯 Reverse WP的更多相关文章

  1. 【CTF】2019湖湘杯 miscmisc writeup

    题目来源:2019湖湘杯 题目链接:https://adworld.xctf.org.cn/task/answer?type=misc&number=1&grade=1&id= ...

  2. CTF 湖湘杯 2018 WriteUp (部分)

    湖湘杯 2018 WriteUp (部分),欢迎转载,转载请注明出处! 1.  CodeCheck(WEB) 测试admin ‘ or ‘1’=’1’# ,php报错.点击登录框下面的滚动通知,URL ...

  3. 2017湖湘杯复赛writeup

    2017湖湘杯复赛writeup 队伍名:China H.L.B 队伍同时在打 X-NUCA  和 湖湘杯的比赛,再加上周末周末周末啊,陪女朋友逛街吃饭看电影啊.所以精力有点分散,做出来部分题目,现在 ...

  4. 2017湖湘杯Writeup

    RE部分 0x01 Re4newer 解题思路: Step1:die打开,发现有upx壳. Step2:脱壳,执行upx -d 文件名即可. Step3:IDA打开,shift+F12看字符串. 点进 ...

  5. Bugku Writeup —文件上传2(湖湘杯)

    我们先来看下题目,题目说明是文件上传 我们可以尝试通过构造payload来进行测试 php://filter/read=convert.base64-encode/resource=flag 获取到f ...

  6. 2018湖湘杯web、misc记录

    1.题目名 Code Check 打开题目,右键发现有id参数的url,简单base64解码以后发现不是明文,说明利用了其他的加密方式,那么应该会有具体的加密方式给我们,于是试试常见的文件泄露,可以发 ...

  7. 湖湘杯2020_ReMe

    查壳后发现是由Python2.7环境下编译得到的exe可执行文件 由此想到可将exe转为pyc文件再反编译成py文件 且该方法只适用于py2 无混淆 因为py3的字节码结构有些许变化 step1: 在 ...

  8. 湖湘杯2020 writeup

    这个平台中间卡的离谱,卡完过后交了flag分还掉了 Web 题目名字不重要 也算是非预期吧,赛后y1ng师傅也说了因为要多端口环境必须这样配,预期解很难 NewWebsite 后台弱口令admin a ...

  9. 2019 安洵杯 Re 部分WP

    0x01.EasyEncryption 测试文件:https://www.lanzous.com/i7soysb 1.IDA打开 int sub_416560() { int v0; // eax i ...

随机推荐

  1. BZOJ 1901 洛谷 P2617 ZOJ 2112 Dynamic Rankings

    以下时空限制来自zoj Time limit 10000 ms Memory limit 32768 kB OS Linux Source Online Contest of Christopher' ...

  2. js控制页面每次滚动一屏,和楼梯效果

    我最近在做我们公司官网的改版,产品中心就是每次滚一屏的,我觉得加上楼梯更方便用户浏览,就随便写了个demo, 先来看看结构,都很简单的 <!--楼梯--> <ul class=&qu ...

  3. 【技术分享:python 应用之二】解锁用 VSCode 写 python 的正确姿势

    之前一直用 notepad++ 作为编辑器,偶然发现了 VScode 便被它的颜值吸引.用过之后发现它启动快速,插件丰富,下载安装后几乎不用怎么配置就可以直接使用,而且还支持 markdown.当然, ...

  4. Selenium 控制浏览器

    webdriver提供了操作浏览器的一些基本方法,例如:打开,前进,后退,刷新,设置窗口大小,截屏,退出等 一.打开网页 代码: # coding = utf-8 from time import s ...

  5. drwxr-xr-x是啥意思

    这里先说一下drwxr-xr-x是啥意思: 第一位表示文件类型.d是目录文件,l是链接文件,-是普通文件,p是管道 第2-4位表示这个文件的属主拥有的权限,r是读,w是写,x是执行. 第5-7位表示和 ...

  6. Spark 2.1.1 源码编译

    Spark 2.1.1 源码编译 标签(空格分隔): Spark Spark 源码编译 环境准备与起因 由于线上Spark On Yarn Spark Streaming程序在消费kafka 写入HD ...

  7. [CSP-S模拟测试]:简单计算(数学)

    题目传送门(内部题104) 输入格式 第一行一个正整数$T$,表示该测试点内的数据组数,你需要对该测试点内的$T$组数据都分别给出正确的答案才能获得该测试点的分数. 接下来$T$组数据,每组数据一行两 ...

  8. http中post 和 get 请求方法区别

    前言 做Web开发就一定会涉及到浏览器和服务器的交互,所以了解浏览器和服务器交互的方式就尤为重要.从接触B/S开始就已经接触到了get和post,但是对它们的了解确实不深入.在后来不断的做项目过程中, ...

  9. Java的LinkedList底层源码分析

    首先我们先说一下,源码里可以看出此类不仅仅用双向链表实现了队列数据结构的功能,还提供了链表数据结构的功能.

  10. POST上传多张图片配合Django接受多张图片

    POST上传多张图片配合Django接受多张图片 本地:POST发送文件,使用的是files参数,将本地的图片以二进制的方式发送给服务器. 在这里 files=[("img",op ...