攻防世界RE练习

攻防世界

一开始学习下re,产生了兴趣

 game

这个题目在某个CTF平台做过了0-0,再做一遍。(跟着WP 0.0)

首先用ExeinfoPe或者Peid查壳

攻防世界RE练习_第1张图片

 

也可以使用file命令查看相关信息

 32位程序,使用ida打开,F5反编译

程序逻辑:

攻防世界RE练习_第2张图片

 

 

shift+F12 查看字符串

攻防世界RE练习_第3张图片

 

进入后

右键list cross reference to ,然后F5

攻防世界RE练习_第4张图片

 

 攻防世界RE练习_第5张图片

 

 

这就是求flag的过程,并且输出,我可以写一个py脚本读出来

在这里的*(&v2+i)相当于v[2+i],数组形式的格式,其实就是递加1==>v2,v3,v4

注:因为初入RE不知道怎么提取,索性复制粘贴,然后运行exec动态变量合并变量值组成数组

exec()函数
v59 = 18 v60 = 64 v61 = 98 v62 = 5 v63 = 2 v64 = 4 v65 = 6 v66 = 3 v67 = 6 v68 = 48 v69 = 49 v70 = 65 v71 = 32 v72 = 12 v73 = 48 v74 = 65 v75 = 31 v76 = 78 v77 = 62 v78 = 32 v79 = 49 v80 = 32 v81 = 1 v82 = 57 v83 = 96 v84 = 3 v85 = 21 v86 = 9 v87 = 4 v88 = 62 v89 = 3 v90 = 5 v91 = 4 v92 = 1 v93 = 2 v94 = 3 v95 = 44 v96 = 65 v97 = 78 v98 = 32 v99 = 16 v100 = 97 v101 = 54 v102 = 16 v103 = 44 v104 = 52 v105 = 32 v106 = 64 v107 = 89 v108 = 45 v109 = 32 v110 = 65 v111 = 15 v112 = 34 v113 = 18 v114 = 16 v115 = 0 v2 = 123 v3 = 32 v4 = 18 v5 = 98 v6 = 119 v7 = 108 v8 = 65 v9 = 41 v10 = 124 v11 = 80 v12 = 125 v13 = 38 v14 = 124 v15 = 111 v16 = 74 v17 = 49 v18 = 83 v19 = 108 v20 = 94 v21 = 108 v22 = 84 v23 = 6 v24 = 96 v25 = 83 v26 = 44 v27 = 121 v28 = 104 v29 = 110 v30 = 32 v31 = 95 v32 = 117 v33 = 101 v34 = 99 v35 = 123 v36 = 127 v37 = 119 v38 = 96 v39 = 48 v40 = 107 v41 = 71 v42 = 92 v43 = 29 v44 = 81 v45 = 107 v46 = 90 v47 = 85 v48 = 64 v49 = 12 v50 = 43 v51 = 76 v52 = 86 v53 = 13 v54 = 114 v55 = 1 v56 = 117 v57 = 126 v58 = 0 a=[] for i in range(59,116): exec('a.append(v{})'.format(i)) print(a) b=[] for i in range(2,59): exec('b.append(v{})'.format(i)) print(b) i=0 c='' while (i<56): a[i]^=b[i] a[i]^=19 c=c+chr(a[i]) i=i+1 print (c)
输出:
[18, 64, 98, 5, 2, 4, 6, 3, 6, 48, 49, 65, 32, 12, 48, 65, 31, 78, 62, 32, 49, 32, 1, 57, 96, 3, 21, 9, 4, 62, 3, 5, 4, 1, 2, 3, 44, 65, 78, 32, 16, 97, 54, 16, 44, 52, 32, 64, 89, 45, 32, 65, 15, 34, 18, 16, 0]
[123, 32, 18, 98, 119, 108, 65, 41, 124, 80, 125, 38, 124, 111, 74, 49, 83, 108, 94, 108, 84, 6, 96, 83, 44, 121, 104, 110, 32, 95, 117, 101, 99, 123, 127, 119, 96, 48, 107, 71, 92, 29, 81, 107, 90, 85, 64, 12, 43, 76, 86, 13, 114, 1, 117, 126, 0]
zsctf{T9is_tOpic_1s_v5ry_int7resting_b6t_others_are_n0t}
locals()函数
v59 = 18
v60 = 64
v61 = 98
v62 = 5
v63 = 2 v64 = 4 v65 = 6 v66 = 3 v67 = 6 v68 = 48 v69 = 49 v70 = 65 v71 = 32 v72 = 12 v73 = 48 v74 = 65 v75 = 31 v76 = 78 v77 = 62 v78 = 32 v79 = 49 v80 = 32 v81 = 1 v82 = 57 v83 = 96 v84 = 3 v85 = 21 v86 = 9 v87 = 4 v88 = 62 v89 = 3 v90 = 5 v91 = 4 v92 = 1 v93 = 2 v94 = 3 v95 = 44 v96 = 65 v97 = 78 v98 = 32 v99 = 16 v100 = 97 v101 = 54 v102 = 16 v103 = 44 v104 = 52 v105 = 32 v106 = 64 v107 = 89 v108 = 45 v109 = 32 v110 = 65 v111 = 15 v112 = 34 v113 = 18 v114 = 16 v115 = 0 v2 = 123 v3 = 32 v4 = 18 v5 = 98 v6 = 119 v7 = 108 v8 = 65 v9 = 41 v10 = 124 v11 = 80 v12 = 125 v13 = 38 v14 = 124 v15 = 111 v16 = 74 v17 = 49 v18 = 83 v19 = 108 v20 = 94 v21 = 108 v22 = 84 v23 = 6 v24 = 96 v25 = 83 v26 = 44 v27 = 121 v28 = 104 v29 = 110 v30 = 32 v31 = 95 v32 = 117 v33 = 101 v34 = 99 v35 = 123 v36 = 127 v37 = 119 v38 = 96 v39 = 48 v40 = 107 v41 = 71 v42 = 92 v43 = 29 v44 = 81 v45 = 107 v46 = 90 v47 = 85 v48 = 64 v49 = 12 v50 = 43 v51 = 76 v52 = 86 v53 = 13 v54 = 114 v55 = 1 v56 = 117 v57 = 126 v58 = 0 a=[] v=locals() for i in range(59,116): a.append(v['v'+str(i)]) print(a) b=[] for i in range(2,59): b.append(v['v'+str(i)]) print(b) i=0 c='' while (i<56): a[i]^=b[i] a[i]^=19 c=c+chr(a[i]) i=i+1 print (c)
输出:

[18, 64, 98, 5, 2, 4, 6, 3, 6, 48, 49, 65, 32, 12, 48, 65, 31, 78, 62, 32, 49, 32, 1, 57, 96, 3, 21, 9, 4, 62, 3, 5, 4, 1, 2, 3, 44, 65, 78, 32, 16, 97, 54, 16, 44, 52, 32, 64, 89, 45, 32, 65, 15, 34, 18, 16, 0]
[123, 32, 18, 98, 119, 108, 65, 41, 124, 80, 125, 38, 124, 111, 74, 49, 83, 108, 94, 108, 84, 6, 96, 83, 44, 121, 104, 110, 32, 95, 117, 101, 99, 123, 127, 119, 96, 48, 107, 71, 92, 29, 81, 107, 90, 85, 64, 12, 43, 76, 86, 13, 114, 1, 117, 126, 0]
zsctf{T9is_tOpic_1s_v5ry_int7resting_b6t_others_are_n0t}

 

Hello CTF

查壳,32位,F5反编译

攻防世界RE练习_第6张图片

 

 

攻防世界RE练习_第7张图片

 

代码的逻辑就是赋予V13为437261636b4d654a757374466f7246756e

输入的长度如果大于17直接break,do while循环17次,中间如果有一个为0的话,就会直接break出循环。没有出现0的话,赋值给v10 直接比较V10和V13是否相等,strcmp相等返回0,提示success

 

这里有个很明显的地方,就是长度17,而437261636b4d654a757374466f7246756e的长度为34,应该是两个两个为一组,16进制的表示。

解密脚本:

import re
MW='437261636b4d654a757374466f7246756e'
secret=re.findall(r'.{2}',MW)
flag=''
for i in secret:
  flag+=chr(int(i,16))
print('flag:'+flag)
输出:
flag:CrackMeJustForFun

open-source

一个C文件,放出centos7中, gcc编译下, gcc code.c

#include 
#include 

int main(int argc, char *argv[]) {
    if (argc != 4) {
        printf("what?\n");
        exit(1);
    }

    unsigned int first = atoi(argv[1]); if (first != 0xcafe) { printf("you are wrong, sorry.\n"); exit(2); } unsigned int second = atoi(argv[2]); if (second % 5 == 3 || second % 17 != 8) { printf("ha, you won't get it!\n"); exit(3); } if (strcmp("h4cky0u", argv[3])) { printf("so close, dude!\n"); exit(4); } printf("Brr wrrr grr\n"); unsigned int hash = first * 31337 + (second % 17) * 11 + strlen(argv[3]) - 1615810207; printf("Get your key: "); printf("%x\n", hash); return 0; }

没学过C,但是看到argv[],与py中的sys.argv应该是一样的。就是获取命令输入的参数

argc是argumentcount的缩写,表示传入main函数的参数个数

argv 是argument vector的缩写,表示传入main函数的参数序列或指针

argv数组下标从0开始,第一个存放的是可执行程序的文件名字

argc[0]表示程序编译后产生的exe文件的路径,数组的长度为argc

第一个条件:

if (argc != 4) {
printf("what?\n");
exit(1);
}

输入的参数要为3个   argc第一个参数为路径

第二个条件:

unsigned int first = atoi(argv[1]);
    if (first != 0xcafe) {
        printf("you are wrong, sorry.\n");
        exit(2);
    }

第一个参数为0xcafe转为十进制数51966

第三个条件:

    unsigned int second = atoi(argv[2]);
    if (second % 5 == 3 || second % 17 != 8) {
        printf("ha, you won't get it!\n");
        exit(3);
    }

第二个参数需要不满足任意一个条件=>整除5余3,整除17余数不能为8。   因此argv[2] 因为25

第四个条件:

if (strcmp("h4cky0u", argv[3])) {
        printf("so close, dude!\n");
        exit(4);
    }

如果第三个参数与h4cky0u相等则返回0绕过if。因此第三个参数为h4cky0u

并非逆向题目,而是C语言的简单源码审计问题

 

simple-unpack

看描述:菜鸡拿到了一个被加壳的二进制文件

我估计是要脱壳。

在这里停一下,去补一下RE基础知识

回来继续看题,二进制文件,不知道该怎么处理。看WP

我用了V2.04版本的Die和exeinfo PE查壳发现可以直接查看到是upx,但是peid不行。

攻防世界RE练习_第8张图片

 

 

 攻防世界RE练习_第9张图片

 

 注:windows下的文件是PE文件,Linux/Unix下的文件是ELF文件

PE文件的全称是Portable Executable,意为可移植的可执行的文件,常见的EXE、DLL、OCX、SYS、COM都是PE文件,PE文件是微软Windows操作系统上的程序文件(可能是间接被执行,如DLL)

通过在爱盘下载了upx(去官网,github下载太慢了,气死)

用upx -d 命令解压脱壳

攻防世界RE练习_第10张图片

 

 攻防世界RE练习_第11张图片

 

 

 

 利用linux中的strings工具也能找到(cmder没有)

攻防世界RE练习_第12张图片

 

 

logmein

明天开始上课了,明儿做把。9.2 0:19

攻防世界RE练习_第13张图片

 

 die太强大了。64位的elf,并且由ubuntu gcc编译

攻防世界RE练习_第14张图片

 

 

 绕过三个条件记能返回成功

攻防世界RE练习_第15张图片

 

 没看wp,自己写了个脚本跑出来8#DO_SVZI*-9*4*2发现不对。再去看下WP把

原理这是是有个大小端存储的问题,并且LL是指长整型

可以按R键转化数据为字符(10进制转16进制,16进制转字符),并且看到了倒序的赋值=》可以推断为小端存储

小端存储:低字节存储在低地址,高字节存储在高地址

大端存储:高字节存储在低地址,低字节存储在高地址

攻防世界RE练习_第16张图片

 

 因此不能光看伪代码,也要结合着汇编看代码段。

因不会C代码0-0,所以只能用py解,附上别人写的C代码写的脚本

py脚本如下:

v8=':"AL_RT^L*.?+6/46'
v7='ebmarah'
v7=v7[::-1]
v6=7
s=''
for i in range(0,17):
s+=chr((ord(v7[i%7]))^ord(v8[i]))
print(s)

C脚本如下:

#include 
#include 
#include 

#define BYTE unsigned char

int main(int argc, char* argv[]) {
    unsigned int i;
    char v8[18] = ":\"AL_RT^L*.?+6/46";
    __int64 v7 = 28537194573619560; int v6 = 7; char s[18] = ""; for (i = 0; i < strlen(v8); ++i) { s[i] = (char)(*((BYTE*)&v7 + i % v6)^v8[i]); } printf("%s\n", s); system("PAUSE"); return 0; }

 

insanity

 先查看,看类型

攻防世界RE练习_第17张图片

 

 攻防世界RE练习_第18张图片

 

 

攻防世界RE练习_第19张图片

 

 攻防世界RE练习_第20张图片

 

 还真是跟题目描述一样,轻松一下。9447{This_is_a_flag}

 

no-strings-attached

查壳

攻防世界RE练习_第21张图片

 

攻防世界RE练习_第22张图片

 

 进入prompt_autthentication

攻防世界RE练习_第23张图片

 

有一个decrypt函数

攻防世界RE练习_第24张图片

 

 

攻防世界RE练习_第25张图片

 

 

看WP需要动态调试,蒙了。可能是函数运行,数据存在于寄存器中把。看WP写把

gdb常用命令

gdb -q xxxx 将文件加载到GDB中

b decrypt 设置断点,decrypt函数

r 运行

s: 执行一行源程序代码,如果此行代码中有函数调用,则进入该函数;
n: 执行一行源程序代码,此行代码中的函数调用也一并执行。

s 相当于其它调试器中的“Step Into (单步跟踪进入)”;
n 相当于其它调试器中的“Step Over (单步跟踪)”。

x 就是用来看内存中的值

info reg 查看寄存器

info break查看断点列表

$eax代表的eax寄存器中的值

到00表示终止了

十六进制表示为:393434377b796f755f6172655f616e5f696e7465726e6174696f6e616c5f6d7973746572797d

攻防世界RE练习_第26张图片

 

 攻防世界RE练习_第27张图片

 

 py2中还有decode('hex'),直接十六进制转化为字符串,py3中没有了

RE很有意思,慢慢来,明早起来看WEB,看之前的难题WP了。

 

python-trade

下下来是一个pyc,直接网上在线的反编译下

import base64

def encode(message):
    s = ''
    for i in message:
        x = ord(i) ^ 32
        x = x + 16
        s += chr(x) return base64.b64encode(s) correct = 'XlNkVmtUI1MgXWBZXCFeKY+AaXNt' flag = '' print 'Input flag:' flag = raw_input() if encode(flag) == correct: print 'correct' else: print 'wrong'

代码十分简单,写一个解密脚本

攻防世界RE练习_第28张图片

 

 

 

getit

查壳

攻防世界RE练习_第29张图片

 

 攻防世界RE练习_第30张图片

 

 貌似是经过一些条件后,写入文件然后又删除的操作

把t写入了flag.txt中,那t应该就是flag。上面还有关于s赋值给t的操作。

0前面的这一块是定义t的,看数据块最后的10E0,10E1,下面是110C

 

0前面的这一块是定义s的

 

这样都有了s和t了,呢么直接写脚本来找到写入的t

直接上解密脚本

t='SharifCTF{????????????????????????????????}'
t=list(t)
s='c61b68366edeb7bdce3c6820314b7498'
v5=0
while(v5<len(s)):
    if(v5&1): v3=1 else: v3=-1 t[v5+10]=chr(ord(s[v5])+v3) v5+=1 yunying='' for i in t: yunying+=i if __name__ == '__main__': print(yunying)

攻防世界RE练习_第31张图片

 

 

 

 csaw2013reversing2

注释:听说运行就能拿到Flag,不过菜鸡运行的结果不知道为什么是乱码

查壳 vc++,32位

攻防世界RE练习_第32张图片

 

 攻防世界RE练习_第33张图片

 

 不管点哪个按钮都直接退掉了。估计是需要调试跳到正确的函数上(可能又是动调)

ida main函数界面:

攻防世界RE练习_第34张图片

 

 这里可以看到比较清晰的程序运行路径

攻防世界RE练习_第35张图片

 

 

int3 =>是一个断点,int3断点

MessageBox 函数用于创建、显示并操作一个消息对话框。该对话框包含由调用程序定义的信息和标题,以及预先定义的图标和按钮

看到IsDebuggerPresent()函数,查文章获得=> https://bbs.pediy.com/thread-226522.htm=>学到一手,大部分的函数返回值都在eax中。难怪之前的decrypt函数需要gdb动态调试到函数查看eax

IsDebuggerPresent()函数是判断程序是否在调试中,因为一些程序为了不被Craker,加入这个函数。

参考(https://www.cnblogs.com/whitehawk/p/10771825.html)od调试(只会一点点)

这里的逻辑是如果是在调试中的话就进入判断运行,如果不在调试中的话直接弹出乱码flag

sub_401000是解密函数,[ebp+lpMem]是乱码存放的地方

sub_401000函数分析出来是将乱码的flag4个字节为一组与0xAABBCCDD异或得到可识别的flag

花了一个小时看OD的WP,没看懂,还是通过IDA来分析把。

sub_401000是解密函数,进入查看

409B10数据如下

攻防世界RE练习_第36张图片

 

409B38处,因为是小端存储,因此需要倒一下

 攻防世界RE练习_第37张图片

 附上别人的WP脚本(OD不会到心态炸裂,无心静态分析)

cipher = [0xbb, 0xcc, 0xa0, 0xbc, 0xdc, 0xd1, 0xbe, 0xb8, 0xcd, 0xcf, 0xbe, 0xae, 0xd2, 0xc4, 0xab, 0x82, 0xd2, 0xd9, 0x93, 0xb3, 0xd4, 0xde, 0x93, 0xa9, 0xd3, 0xcb, 0xb8, 0x82, 0xd3, 0xcb, 0xbe, 0xb9, 0x9a, 0xd7, 0xcc, 0xdd]
key = [0xbb,0xaa,0xcc,0xdd]

flag = ''
for i in range(len(cipher)):
    flag += chr(cipher[i]^key[i%4])

print flag
————————————————
版权声明:本文为CSDN博主「Prowes5」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/Prowes5/article/details/100409391

RE到此为止,冲WEB

9.29重做,用OD动调找到了flag,开森。最近学了一些汇编知识,正好派上了用场。开心

 

 先ida静态分析

攻防世界RE练习_第38张图片

 

 攻防世界RE练习_第39张图片

 

 可以看出有个IsDebuggerPresent,意思是如果在调试中返回非零值,如果不是则直接返回0

我们应该是需要进入这里,sub_401000应该是一个解密函数,并且上面有int 3 断点

攻防世界RE练习_第40张图片

 

 利用OD载入,查找ASCII,找到flag,在00BB1088处断点

攻防世界RE练习_第41张图片

 

即跳过ISDebuggerpresent函数,进入解密区

攻防世界RE练习_第42张图片

 

 下断点单步F8运行

攻防世界RE练习_第43张图片

 

发现直接跳到了00BB10B9这里,中间跳了呢么多,我们尝试修改未跳转的jnz,让他跳转到下面被跳过的区域。查看下会发生什么

修改je并且nop了int3后,又有一个想跳转出去,不执行里面的东西,肯定有蹊跷。

攻防世界RE练习_第44张图片

 

 

 

 很想在ida中进行的如下步骤

 

 nop掉继续尝试,text里什么都没有

 

又想要跳出去,不行,接着看

 

 发现nop后,也无法继续单步运行。那就尝试跳转到下面的语句中。有两个MessageBoxA,那肯定有一个是假的

攻防世界RE练习_第45张图片

 

 继续单步F8,F7是步入,会进入call函数。没必要

 

 攻防世界RE练习_第46张图片

 

 其实与ida上的静态分析是一样的,我们需要进入if判断中,并且让解密函数运行即汇编中的解密call指令运行,但是不能让他直接退出,要让将我们解密后需要的值返回到一个可以看到的变量上,将之跳转到第二个Messagebox上,值就会传到Text上。第一个Messagebox是设置的陷阱,不能nop而是要避开并且跳转到正确的Messagebox上。

设置的断点最好也要取核心位置,正要进入判断的位置上,学到了很多。悟通了

攻防世界RE练习_第47张图片

 通过IDA和OD的对比也能发现解密函数其实就是那个被跳过的Call

攻防世界RE练习_第48张图片

 

 攻防世界RE练习_第49张图片

maze

查壳,elf文件,64位,GCC编译,amd64

攻防世界RE练习_第50张图片

 攻防世界RE练习_第51张图片

 

 

 绕过第一个if,需要输入的前五个字符与nctf{相等,并且输入的字符需要24位,并且最后一位必须是}

如果大于N进入第一个if,判断是否是大写O或小写0,进入不同的函数。如果小于N,是否等于.或者0在进入不同的函数

题目描述是一个迷宫,可能O,o,.,0代表着上下左右。并且最后要经过

攻防世界RE练习_第52张图片

 

 

 

 绕过这个if,使之相等后,才能Congratulations!

我们来查看等于O,o执行的函数

O:

攻防世界RE练习_第53张图片

 

 o:

攻防世界RE练习_第54张图片

 

 .:

攻防世界RE练习_第55张图片

 

 0:

攻防世界RE练习_第56张图片

 

分析得V9应该是存储坐标的地方,并且每走一步,都会判断,如果超出限制范围,就会直接回到LABEL_22处,puts('wrong flag')

攻防世界RE练习_第57张图片

 

 最后会判断是否等于35,不等的话,直接wrong,flag。相等的话,就是LABEL_20

攻防世界RE练习_第58张图片

 

 这里可以看出,当走完后,如果不是#的话,还是wrong flag,因此可以判断#就是我们需要走到的重点。

SHIDWORD是取下一个字节的意思,再结合上面的O,o,.,0,和迷宫的字符数量为64。所以是8*8的地图

因此V9应该是行数,V9+1是下一个字节的地址,表示的是列

因此把迷宫搞下来,变成8*8

攻防世界RE练习_第59张图片

 

 shift+e,搞下来用py脚本,变成8*8

# -*- coding: utf-8 -*-
a='  *******   *  **** * ****  * ***  *#  *** *** ***     *********'
for i in range(0,len(a)):
    if(i%8==0):
        print('')
    print(a[i],end='')

 攻防世界RE练习_第60张图片

 

右下右右下下左下下下右右右右上上左左

o0oo00O000oooo..OO

flag就是nctf{o0oo00O000oooo..OO}

终于解完了RE的新手题目

dmd-50

suctf-2016题目

国庆10.1分还无聊到做RE题?我大概是蛋疼极了

查壳

攻防世界RE练习_第61张图片

 

 攻防世界RE练习_第62张图片

 

 攻防世界RE练习_第63张图片

 非常的多,逻辑上看起来不复杂,其中还有一个MD5的函数,就是看不懂这些C中的头文件类啊定义什么的。(学过半年的C++,只是应付考试QAQ)

运行如下

 

攻防世界RE练习_第64张图片

 

 注意下这里,V41是由V40传过来的,然后上面有个MD5函数

攻防世界RE练习_第65张图片

应该是md5后,如果是每一位对照下面的这个md5哈希值的话,如果相同的话,弹invaild key,因此只要把哈希值解一遍就好

攻防世界RE练习_第66张图片

 

 攻防世界RE练习_第67张图片

 

 

 

 直接交flag就完事了。(对于那些C的东西,懵逼啊哎,也不会IDA中的idc和python脚本,每个十进制ascii都是我按R按出来的)

Shuffle

题目描述是找到字符串在随机化之前.

查壳

攻防世界RE练习_第68张图片

 

 

 

BUGKU

瞎玩玩

逆向入门

查壳

攻防世界RE练习_第69张图片

 

打开也打开不了.用ultraedit打开瞧瞧

攻防世界RE练习_第70张图片

 

 找个在线base64转图片的网站

攻防世界RE练习_第71张图片

 

 扫描拿到flag

love

查看

攻防世界RE练习_第72张图片

 

 32位C++,拖入ida

攻防世界RE练习_第73张图片

 

 

 

 

strncpy函数用于将指定长度的字符串复制到字符数组中,char *strncpy(char *dest, const char *src, int n),表示把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,并返回被复制后的dest
strncmp函数为字符串比较函数,字符串大小的比较是以ASCII 码表上的顺序来决定,此顺序亦为字符的值。其函数声明为int strncmp ( const char * str1, const char * str2, size_t n );功能是把 str1 和 str2 进行比较,最多比较前 n 个字节,若str1与str2的前n个字符相同,则返回0;若s1大于s2,则返回大于0的值;若s1 小于s2,则返回小于0的值
  

这样思路就比较清晰了。

首先传入字符串,然后经过函数sub_4110BE后传入v4

再将 v4的前28个字节传入DEST数组中

攻防世界RE练习_第74张图片

 

 对DEST数组进行处理,然后比较str2和dest前v5个字符是否相等,相等则right flag!

查看一下函数

攻防世界RE练习_第75张图片

 

 

 

 

攻防世界RE练习_第76张图片

 

 v3是传入字符串的长度,然后将a2除于3后,又乘上4,想到了什么?base64加密

base64加密,一个字符占6个字符,3个字符24个字节被加密成4个字符24个字节

呢么直接上脚本,唯一处理的只有这两处

攻防世界RE练习_第77张图片

 

 

 

 python3脚本

import base64
str1='e3nifIH9b_C@n@dH'
str2=''
for i in range(len(str1)):
    a=ord(str1[i])-i
    str2+=chr(a)
print(base64.b64decode(str2.encode('utf8')).decode())

攻防世界RE练习_第78张图片

 

 睡觉了

 

你可能感兴趣的:(攻防世界RE练习)