Polar靶场reverse方向通关题解

最近备战国赛刷刷题找手感,找了个还不错的靶场,小众但是题目质量还可以,下面是已经做的题的wp,不定时更新做题进度。

目录

简单难度

shell

PE结构

拼接

加加减减

康师傅

 另辟蹊径

use_jadx_open_it

re2

Why32

?64

 Sign Up

easyre1

babyRe

C^

一个flag劈三瓣儿

EasyCPP2

crc

 box

HowTo_Login

中等难度

JunkCode

RevMethod

逆一下子

解法1

解法2

可以为师

左右为难

Java_Tools

困难难度


简单难度

shell

先进行upx脱壳

放入IDA直接找到flag即可

PE结构

对文件头进行修复

IDA打开,找到字符串

反编译

写个简单的异或脚本

a = 'eobdx55:;4bgg30`:;b;e3`b`42f7`be`1b5b~'
flag = ''
for i in range(0,len(a)):
    flag += chr(ord(a[i]) ^ 3)
print(flag)

或者直接运行exe文件

拼接

一个很简单那的字符串拼接

IDA打开就行

加加减减

IDA打开,就是对每个字符的ascll码减去数组下标

解密脚本

str = "ek`fz5123086/ce7ac7/`4a81`6/87b`b28a5|"
result = ''.join(chr(ord(c) + 1) for c in str)
print(result)

康师傅

IDA打开,一个简单的异或

 

解密脚本

a = 'oehnr8>?;<?:9k>09;hj00o>:<o?8lh;8h9l;t'
flag = ''
for i in range(0,len(a)):
    flag += chr(ord(a[i]) ^ 9)
print(flag)

 另辟蹊径

运行程序,是一个典型的改值题

使用Cheat Engine>选择进程>输入100000>扫描

 

 
双击改值

再去点击一下就行了

如果会动态调试的话可以用OD来做

打开后F9运行

句柄,刷新

其实这就是flag

use_jadx_open_it

直接用jadk打开

搜索main关键词

打开mainactivity,可以直接看到flag

re2

IDA打开,找到主函数点进去就看到了

Why32

IDA打开,找到主函数

写个脚本

a = '2gfe8c8c4cde574f7:c6c;:;3;7;2gf:'
flag = ''
for i in range(0,len(a)):
    flag += chr(ord(a[i]) - 2)
print(flag)

 运行结果是md5值,还需要进行md5解密

?64

尝试运行

base64解密,再对解密得到的内容进行md5加密

 Sign Up

IDA打开,找到对登陆账号密码判断的函数

对账号的前七位-1,密码的四位-2

点开查看加密前的账号密码

由此得到账号:081057009密码:pmmr

flag{md5(账号密码)}

easyre1

不知道为什么反编译不完全,勉强做了一下

找到函数(主函数没反编译出来,看内存也可以看懂)

传入一个字符串

d^XSAozQPU^WOBU[VQOATZSE@AZZVOF

还有一个key

参考了其他师傅的题解,正常反编译出来就是前一个字符串按位-1和数字字符串进行异或

搓个脚本

result='d^XSAozQPU^WOBU[VQOATZSE@AZZVOF'
key = '5055045045055045055045055045055'
flag = ''
for i in range(len(key)):
    flag += chr((ord(result[i])+1) ^ ord(key[i]))

print(flag)

flag{PolarDNbecomesbiggerandstronger}

babyRe

IDA打开

找main函数

查看encode函数

就是对flag进行按位+2操作

查看字符串找到明文

写脚本

a='asdfgcvbnmjgtlop'

flag = ''
for i in range(len(a)):
    flag += chr((ord(a[i])+2))
print(flag)

flag{cufhiexdpolivnqr}

C^

IDA打开找到主函数

操作在funl中,和1进行异或

check函数中查看字符串

脚本

a='shfiu777'
flag = ''
for i in range(len(a)):
    flag += chr((ord(a[i])) ^ 1)
print(flag)

flag{}要md5{right}

一个flag劈三瓣儿

EasyCPP2

IDA打开,找到字符串

跟到主函数

解密脚本

a='qisngksofhuivvmg'
flag = ''
for i in range(len(a)):
    flag += chr((ord(a[i]) + 3) ^ 1)
print(flag)

crc

IDA打开找到主函数

打开strmncpy函数,是从输入的内容中进行字段选择的过程

打开magic函数,是CRC32计算

再回到main函数进行综合分析

这几个8位十六进制数其实就是从flag中取出1-4个字段进行crc计算后的结果

写了个通用的爆破脚本

import binascii
import string

print('-------------Start Crack CRC-------------')

def crack_crc_1(target):
    comment = ''
    chars = string.printable
    for crc_value in target:
        for char1 in chars:
            char_crc = binascii.crc32(char1.encode())  # 获取遍历字符的CRC32值
            calc_crc = char_crc & 0xffffffff  # 将获取到的字符的CRC32值与0xffffffff进行与运算
            if calc_crc == crc_value:  # 将每个字符的CRC32值与每个文件的CRC32值进行匹配
                comment += char1
    print('{}'.format(comment))


def crack_crc_2(target):
    comment = ''
    chars = string.printable
    for crc_value in target:
        for char1 in chars:
            for char2 in chars:
                res_char = char1 + char2  # 获取遍历的任意2Byte字符
                char_crc = binascii.crc32(res_char.encode())  # 获取遍历字符的CRC32值
                calc_crc = char_crc & 0xffffffff  # 将获取到的字符的CRC32值与0xffffffff进行与运算
                if calc_crc == crc_value:  # 将获取字符的CRC32值与每个文件的CRC32值进行匹配
                    comment += res_char
    print('{}'.format(comment))


def crack_crc_3(target):
    comment = ''
    chars = string.printable
    for crc_value in target:
        for char1 in chars:
            for char2 in chars:
                for char3 in chars:
                    res_char = char1 + char2 + char3  # 获取遍历的任意3Byte字符
                    char_crc = binascii.crc32(res_char.encode())  # 获取遍历字符的CRC32值
                    calc_crc = char_crc & 0xffffffff  # 将遍历的字符的CRC32值与0xffffffff进行与运算
                    if calc_crc == crc_value:  # 将获取字符的CRC32值与每个文件的CRC32值进行匹配
                        comment += res_char
    print('{}'.format(comment))

def crack_crc_4(target):
    comment = ''
    chars = string.printable
    for crc_value in target:
        for char1 in chars:
            for char2 in chars:
                for char3 in chars:
                    for char4 in chars:
                        res_char = char1 + char2 + char3 + char4  # 获取遍历的任意4Byte字符
                        char_crc = binascii.crc32(res_char.encode())  # 获取遍历字符的CRC32值
                        calc_crc = char_crc & 0xffffffff  # 将遍历的字符的CRC32值与0xffffffff进行与运算
                        if calc_crc == crc_value:  # 将获取字符的CRC32值与每个文件的CRC32值进行匹配
                            comment += res_char
    print('{}'.format(comment))


if __name__ == '__main__':
    crack_crc_4([0xd1f4eb9a])
    crack_crc_1([0x15d54739])
    crack_crc_4([0x540bbb08])
    crack_crc_2([0x3fcbd242])
    crack_crc_4([0x2479c623])
    crack_crc_1([0xfcb6e20c])

print('-----------CRC Crack Completed-----------')

运行结果

 box

IDA找到主函数

分别点开key1,key2,key3

一个比较简单的flag拼接题

flag1是一个简单的数字处理

脚本

c, d, f = 0, 0, 0
key = 0

for i in range(1, 22):
    for j in range(1, 2):
        c += i
        d += c
        f = d + c - 1

for k in range(33, 0, -1):
    c = f * d // 10
    key += f * d // 10

print(key)

 key1:11694441

flag2直接点开就是了

key2:that_ok

flag3一段base32密文

flag{md5(11694441that_okkey)}

HowTo_Login

打开主函数

打开DialogFunc

密码就是CZ9dmq4c8g9G7bAX

flag{md5(CZ9dmq4c8g9G7bAX)}

中等难度

JunkCode

一道花指令的题

IDA打开后通过内存可以大概做出题目,但按照题目的本意应该是要进行花指令去除的

那么开始正规的解题过程

jz就是判断条件为1就跳转

但00411AC4为花指令,后面的内容无法被正常识别和解析,导致反编译失败

具体的操作方法是:选中内存地址00411AC4,按U键进行undefine

选中00411AC5处按C键MakeCode,再将00411AC4处的字节内容改为0x90

再选中00411AC5处按C键MakeCode

最后到函数头位置按P构建函数

再进行反编译

和刚开始看内存时的猜测一样,就是进行一次异或

解密脚本

a = 'dnceyhwli]amfg]kq]dwll{'
flag = ''
for i in range(0,len(a)):
    flag += chr(ord(a[i]) ^ 2)
print(flag)

RevMethod

IDA打开有很多flag

IDA打开主函数 ,在随机生成flag

下面是对flag是否正确的判断过程

可以看出判断的是所找到的flag内存地址和预设的是否相同

并且通过每一位的比较,不断确定是否正确,显然每个flag的前五位都是一样的

所以不管找到哪个地址,前五位都是没有参考性的,但再往后两位就就可以确定flag了说明2566就是最后的flag所在的内存地址的位置41A000+A06

找到对应的内存位置

逆一下子

解法1

IDA打开,找到主函数

点进sub_401180

c68d-d262-5b91-2541-1ba7-1f3d-8103-41c4将中间的连接号去除就是flag

解法2

使用Resource Hacker打开

修改后点右上角的绿色三角进行编译,最后保存

再打开就可以点flag了

可以为师

可以发现帮助按钮点击不了

还是使用Resource Hacker打开

还是和上题一样

改完就可以打开了

flag{a5dd39834f606a4c00cc83d507c5e599}

左右为难

一个迷宫题

IDA打开发现迷宫

整理一下

flag{md5(sssssdddddwwaawwdddwddsssddwwddssdss)}

IDA打开找到主函数

 Check_Length,判断输入的长度为37

主函数,创建了一个长度为3737的字符串

x()函数,每位分别与一个每次增长1的j进行异或

点开j看到初始值为8

 check()函数,对密文`lfgc-y`b}v!进行检查

 所以虽然有很多地方不明白具体的原因,但依旧可以正常的解题

写一个脚本

a = '`lfgc-y`b}v!'
result = ''
j = 8
for i in range(len(a)):
        result += chr(ord(a[i]) ^ j)  # 将字符的 ASCII 值减去索引后添加到 result
        j = j + 1
print(result)

要注意的是,异或过程中,最后一位未进行

所以明文是hello world!

flag{md5(hello world!)}

Java_Tools

用jadx打开

main主函数

package main.java;

import java.util.Scanner;

/* loaded from: Test.class */
public class Test {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.println("Welcome to Polar_Ctf!,come to play!");
        System.out.println("Please Input : ");
        String name = in.next();
        char[] Strings = name.toCharArray();
        Tools.Add_1(Strings, 3);
        Tools.Re(Strings);
        Tools.Judge(Strings);
    }
}

 调用了三个函数

A_dd1、Re、Judge

打开Tool看看各个函数的功能

package main.java;

import java.util.ArrayList;

/* loaded from: Tools.class */
public class Tools {
    public static int j = 6;

    public static void Re(char[] str) {
        for (int i = 0; i < (str.length / 2) - 1; i++) {
            char temp = str[i];
            str[i] = str[(str.length - i) - 1];
            str[(str.length - i) - 1] = temp;
        }
    }

    public static void Xor(char[] str) {
        for (int i = 0; i < str.length; i++) {
            str[i] = (char) (str[i] ^ j);
        }
    }

    public static void Add_1(char[] str, int x) {
        for (int i = 0; i < str.length; i++) {
            str[i] = (char) (str[i] + x);
        }
    }

    public static void Judge(char[] str) {
        ArrayList<Character> Result = new ArrayList<>();
        ArrayList<Character> Flag = new ArrayList<>();
        for (char c : str) {
            Character i = Character.valueOf(c);
            Result.add(Character.valueOf(i.charValue()));
        }
        String sttr = new String(str);
        if ("$gourZroohK".contains(sttr)) {
            System.out.println("You Are Right!MD5!");
        } else {
            System.out.println("You Are Wrong! please try it again!");
        }
        char[] Strings = "$gourZroohK".toCharArray();
        for (char c2 : Strings) {
            Flag.add(Character.valueOf(c2));
        }
        if (Result.equals(Flag)) {
            System.out.println("You Are Right!MD5!");
        } else {
            System.out.println("You Are Wrong! please try it again!");
        }
    }
}

 由此可知,A_dd1是对字符串进行前后按位互换,Re对每一位进行了+3操作,Judge进行了字符串的比较。所以密文就是

$gourZroohK

手动换位就行

KhoorZruog$

每位-3

s = "KhoorZruog$"
s_list = list(s)

for i in range(len(s_list)):
    s_list[i] = chr(ord(s_list[i]) - 3)
s = ''.join(s_list)

print(s)

 flag{md5(HelloWorld!)}

PY_RE

下载两个py文件

Test.py

将后一半和字典数组进行比较,将字母换成对应的下标

def EnData1(Input_Str,Dict):
    for i in range(int(len(Input_Str)/2),len(Input_Str)):
        for dict in Dict:
            if Input_Str[i] == str(dict):
                Input_Str[i] = Dict[dict]
                break
def Judge(Input_Str):
    FLAG = ['H', 'E', 'L', 'L', 'O', '_', '_', 11, 2, 7, 19, 12, 13]
    if str(Input_Str) == str(FLAG):
        print("YES!")
    else:
        print("NO!")
all_data = []
def EnData(Input_Str,Dict):
    for i in range(int(len(Input_Str)/2),len(Input_Str)):
        flag = 0
        for dict in Dict:
            if Input_Str[i] == dict:
                all_data.append(Dict[dict])
                flag = 1
        if  flag == 0:
            all_data.append(Input_Str[i])

start.py

生成字典的文件,其实可以直接看出字典的内容,也可以输出一下

#import Test
Dict = {}
key = 'A'
value = 26
for i in range(1,27):
    Dict.setdefault(key, value)
    key = chr(ord(key) + 1)
    value = value - 1
print("===================Py_Reverse====================")

#print(Dict)

def main():
    Input_Str = input("Please Input Str:\n")
    Input_Str = list(Input_Str)
    Test.EnData1(Input_Str,Dict)
    Test.Judge(Input_Str)
main()

得到字典

{'A': 26, 'B': 25, 'C': 24, 'D': 23, 'E': 22, 'F': 21, 'G': 20, 'H': 19, 'I': 18, 'J': 17, 'K': 16, 'L': 15, 'M': 14, 'N': 13, 'O': 12, 'P': 11, 'Q': 10, 'R': 9, 'S': 8, 'T': 7, 'U': 6, 'V': 5, 'W': 4, 'X': 3, 'Y': 2, 'Z': 1}

将对应的数字换掉

HELLO__PYTHON

二层防御

UPX壳直接脱就行

IDA打开先看主函数

点开看看最后的check函数有没有什么操作

没什么操作,但是得到了flag1的值。那就直接看上一个sub122(x)

对str进行了一次前后互换

点开sub133看看

给出两个值v1=1;x1=j跟进一下看到j=8。同时将每一位-1之后和x1进行了异或

再看前的strlen和Check_Length()函数都未进行操作

所以逆向思路也很简单,每位+1,与8异或,最后进行反转就行

但有个小细节要注意,在进行反转和异或等操作时,都是从第二个字符到倒数第二个,也就是第一个和倒数第一个是不变的。

脚本随便写一个

flag1 = 'allo_PWN n'
for i in range(len(flag1)):
    flag1 += chr((ord(flag1[i]) + 1) ^ 8)

print(flag1)

手动翻转一下就行

aeexhYPG)n——>a)GPYhxeen

最后md5就是flag(这一步在汇编里也有所体现,不再赘述)

困难难度

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值