首页 > 其他分享 >buuctf re wp部分合集

buuctf re wp部分合集

时间:2024-06-05 21:44:57浏览次数:15  
标签:buuctf 函数 add a1 re flag wp 字符串 ord

1.reverse2

将文件用IDA打开,shift+f12找到字符串

image-20240404195211940

转入主函数

从主函数可以看出,for循环中将flag中的‘i'和‘r'转换为字符’1‘,然后判断输入的字符串和flag是否相同,然后找到flag所存字符串image-20240404195538542

按上述方式变换字符后,即得到flag{hack1ng_fo1_fun}

题目reverse1同理

2.新年快乐

先查壳,发现有upx壳

image-20240404202859272

image-20240404202920279

使用工具脱壳后,用IDA搜索字符串

image-20240404203022555

根据题目提示,此字符串即为flag

3.xor

将文件拖入IDA

image-20240405085125858

函数要将输入的字符串逐位异或后与 global 进行比对

查找global

image-20240405085411290

编写EXP进行反异或

image-20240405090731425

得到flag{QianQiuWanDai_YiTongJiangHu}

4.reverse3

拖入IDA中查看主函数

image-20240405093025133

主要部分是将输入的字符串的每个字符加上其所在位置的数字来进行简单的加密

查询字符串

image-20240405093559613

根据此猜测字符串使用了base64加密

然后编写EXP将str2进行解密

image-20240405093716390

得到flag{i_l0ve_you}

5.helloworld

.apk文件,安卓逆向,使用JEB

image-20240405094726894

6.不一样的Flag

image-20240414135616778

查看主函数中有上下左右信息,还有一串01字符串,推测为迷宫,#为终点。

image-20240414135752857

可以得到flag{222441144222}

7.SimpleRev

img

主要函数依据key字符串对v2进行加密操作,得到的str2与上面操作所得text相同,所以需要写解密的EXP。

在IDA中找到变量代表的字符串

src与v10是由16进制直接转换为字符,本质是小端存储的十六进制,解密时应将src与v10字符串倒置再拼接

#出现的变量
key1 = 'ADSFK'
key3 = 'kills'
src = 'SLCDN'
v10 = 'wodah'

#LODWORD(v0) = join(key3, &v10)
v0 = key3
for i in range(len(v10)-1, -1, -1):
    v0 += v10[i]
print(v0)
#strcat(key, src)
key = key1
for i in range(len(src)-1, -1, -1):
    key += src[i]
print(key)
#第一个循环:key大写转化为小写
tmp = ''
for i in key:
    value = ord(i) + 32
    tmp += chr(value)
key = tmp
print(key)
#第二个循环,逆向求出flag
str2 = text = v0
flag = ''
for i in range(len(str2)):
    value1 = ord(str2[i])
    value1 -= 97

    value2 = -ord(key[i])
    value2 += 97
    value2 -= 39

    value = value1 - value2
    while True:
        if value > ord('Z'): value -= 26
        elif value < ord('A'): value += 26
        else: break
    flag += chr(value)

print(flag)
8.luck_guy

64位程序,拖入IDA,惯例shift+f12

image-20240427150255114

找到疑似指向flag字符串

image-20240427150800470

跟进后ctrl+x

找到函数后F5进入反汇编

image-20240427152059657

可以看到s是由f1和f2拼接而成,f1可以跟进,得到一半flag---GXY{do_not_

另一半则是f2进行case5操作得到,写EXP

f1 = 'GXY{do_not_'
f2 = [0x7F, 0x66, 0x6F, 0x60, 0x67, 0x75, 0x63, 0x69][::-1]
flag = ''
for i in range(8):
    if i % 2 == 1:
        f2[i] -= 2
    else:
        f2[i] -= 1
    f1 += chr(f2[i])
print(f1)

得到flag{do_not_hate_me}

9.java逆向

将文件拖入jd gui中

image-20240429185303366

函数操作就是先将输入的字符数组每个字符的ASCII值+64,再与0x20异或,最后与KEY比较是否相同

写EXP

KEY = [180, 136, 137, 147, 191, 137, 147, 191, 148, 136,133, 191, 134, 140, 129, 135, 191, 65]
flag = ''
for i in range(0, len(KEY)):
    value = KEY[i]
    value ^= 0x20
    value -= 64
    flag += chr(value)
print(flag)

得到flag{This_is_the_flag_!}

10.刮开有奖

拖入IDA查看字符串

image-20240504190753909

可疑字符串,跟进后ctrl+x查看交叉引用然后f5反汇编

image-20240504190908802

image-20240504190920429

找到疑似flag字符串和一个函数image-20240504192128256

可以猜测flag为8个字符,然后跟进sub_4010F0函数

image-20240504192356646

把伪代码直接改写成c语言代码(伪代码是地址寻址,比如a1 + i*4 代表的就是a1[i] *4是因为int型占四个字节,如果是char型就不需要 *4)

#include <stdio.h>
int sub_4010F0(char *a1, int a2, int a3)
{
    int result; // eax
    int i;      // esi
    int v5;     // ecx
    int v6;     // edx

    result = a3;
    for (i = a2; i <= a3; a2 = i)
    {
        v5 = i;
        v6 = a1[i];
        if (a2 < result && i < result)
        {
            do
            {
                if (v6 > a1[result])
                {
                    if (i >= result)
                        break;
                    ++i;
                    a1[v5] = a1[result];
                    if (i >= result)
                        break;
                    while (a1[i] <= v6)
                    {
                        if (++i >= result)
                            goto LABEL_13;
                    }
                    if (i >= result)
                        break;
                    v5 = i;
                    a1[result] = a1[i];
                }
                --result;
            } while (i < result);
        }
    LABEL_13:
        a1[result] = v6;
        sub_4010F0(a1, a2, i - 1);
        result = a3;
        ++i;
    }
    return result;
}
int main()
{
    char str[] = "ZJSECaNH3ng";
    sub_4010F0(str, 0, 10);
    printf("%s\n", str);
    getchar();
    return 0;
}

运行得到加密后的字符串

3CEHJNSZagn

看下一部分

image-20240504210103632

跟进函数,发现是个很复杂的函数,但是还有个可跟进函数image-20240504210145479

根据主要函数image-20240504210222573

推测是将v4和v5经过base64加密的到ak1w和V1Ax,解密后得到

v4 = jMp
v5 = WP1

最后看最后部分,写个EXP

string = '3CEHJNSZagn'
flag = ''
flag += chr(ord(string[0]) + 34)
flag += string[4]
flag += chr(((ord(string[2]) * 3) + 141) // 4)
flag += chr(((ord(string[7]) // 9) * 2) * 4)
print(flag)

得到结果

UJWP //前四个字符

因为flag长度为8,所以WP应该是直接重叠拼进去

得到flag{UJWP1jMp}

11.简单注册器

.apk文件,拖入JEB,主函数tab反汇编

image-20240506185107986

找到主要函数,很简单的加密,写个EXP

arr1 = 'dd2940c04462b4dd7c450528835cca15'
arr = list(arr1)
arr[2] = chr(ord(arr[2]) + ord(arr[3]) - 50)
arr[4] = chr(ord(arr[2]) + ord(arr[5]) - 0x30)
arr[30] = chr(ord(arr[0x1F]) + ord(arr[9]) - 0x30)
arr[14] = chr(ord(arr[27]) + ord(arr[28]) - 97)
for i in range(16):
    a = arr[0x1F - i]
    arr[0x1F - i] = arr[i]
    arr[i] = a
arr1 = ''.join(arr)
print(arr1)

得到flag{59acc538825054c7de4b26440c0999dd}

12.[ACTF新生赛2020]easyre

查壳,UPX壳,32位程序

image-20240506185837793

脱壳后拖入IDA

找到main函数反汇编

image-20240506190106896

从for循环看出flag应该是12位,循环内容就是以flag的ASCII值-1为索引在byte_402000数组中搜索字符与v4字符串数组比较是否相同

写EXP,反向一下for循环

v4 = [0x2A, 0x46, 0x27, 0x22, 0x4E, 0x2C, 0x22, 0x28, 0x49, 0x3F, 0x2B, 0x40]
string = '~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)(' + chr(
    0x27) + '&%$# !"'
flag = ''
for i in v4:
    for j in range(1, len(string)):
        if i == ord(string[j]):
            flag += chr(j + 1)
print("flag{" + flag + "}")
13.[GWCTF 2019]pyre

使用反编译

#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 2.7

print 'Welcome to Re World!'
print 'Your input1 is your flag~'
l = len(input1)
for i in range(l):
    num = ((input1[i] + i) % 128 + 128) % 128
    code += num

for i in range(l - 1):
    code[i] = code[i] ^ code[i + 1]

print code
code = [
    '%1f',
    '%12',
    '%1d',
    '(',
    '0',
    '4',
    '%01',
    '%06',
    '%14',
    '4',
    ',',
    '%1b',
    'U',
    '?',
    'o',
    '6',
    '*',
    ':',
    '%01',
    'D',
    ';',
    '%',
    '%13']

然后将加密逆向

code = ['\x1f', '\x12', '\x1d', '(', '0', '4', '\x01', '\x06', '\x14', '4', ',', '\x1b', 'U', '?', 'o', '6', '*', ':',
        '\x01', 'D', ';', '%', '\x13']
flag = ''
length = len(code)
for i in range(length):
    code[i] = ord(code[i])

for i in range(length - 1, 0, -1):
    code[i - 1] = code[i] ^ code[i - 1]

for i in range(length):
    code[i] = code[i] - i
    if code[i] <= 0:
        code[i] += 128
    flag += chr(code[i])

print(flag)

得到flag{Just_Re_1s_Ha66y!}

14.findit

.apk用JEB反汇编

image-20240507195421135

得到函数,下面的if函数的循环中字符串疑似flag有关,直接放IDEA运行

public class Main {
    public static void main(String[] args) {
        char[] y = new char[38];
        for (int i = 0; i < 38; ++i) {
            if (new char[]{'p', 'v', 'k', 'q', '{', 'm', '1', '6', '4', '6', '7', '5', '2', '6', '2', '0', '3', '3', 'l', '4', 'm', '4', '9', 'l', 'n', 'p', '7', 'p', '9', 'm', 'n', 'k', '2', '8', 'k', '7', '5', '}'}[i] >= 65 && new char[]{'p', 'v', 'k', 'q', '{', 'm', '1', '6', '4', '6', '7', '5', '2', '6', '2', '0', '3', '3', 'l', '4', 'm', '4', '9', 'l', 'n', 'p', '7', 'p', '9', 'm', 'n', 'k', '2', '8', 'k', '7', '5', '}'}[i] <= 90 || new char[]{'p', 'v', 'k', 'q', '{', 'm', '1', '6', '4', '6', '7', '5', '2', '6', '2', '0', '3', '3', 'l', '4', 'm', '4', '9', 'l', 'n', 'p', '7', 'p', '9', 'm', 'n', 'k', '2', '8', 'k', '7', '5', '}'}[i] >= 97 && new char[]{'p', 'v', 'k', 'q', '{', 'm', '1', '6', '4', '6', '7', '5', '2', '6', '2', '0', '3', '3', 'l', '4', 'm', '4', '9', 'l', 'n', 'p', '7', 'p', '9', 'm', 'n', 'k', '2', '8', 'k', '7', '5', '}'}[i] <= 0x7A) {
                y[i] = (char) (new char[]{'p', 'v', 'k', 'q', '{', 'm', '1', '6', '4', '6', '7', '5', '2', '6', '2', '0', '3', '3', 'l', '4', 'm', '4', '9', 'l', 'n', 'p', '7', 'p', '9', 'm', 'n', 'k', '2', '8', 'k', '7', '5', '}'}[i] + 16);
if (y[i] > 90 && y[i] < 97 || y[i] >= 0x7A) {
   y[i] = (char) (y[i] - 26);
         		}
            } else {
                y[i] = new char[]{'p', 'v', 'k', 'q', '{', 'm', '1', '6', '4', '6', '7', '5', '2', '6', '2', '0', '3', '3', 'l', '4', 'm', '4', '9', 'l', 'n', 'p', '7', 'p', '9', 'm', 'n', 'k', '2', '8', 'k', '7', '5', '}'}[i];
            }
        }
        System.out.println(y);
    }
}

直接得到结果flag{c164675262033b4c49bdf7f9cda28a75}

这道题其实是个凯撒加密,将字符串整体偏移10后也可以得到flag

15.[ACTF新生赛2020]rome

32位程序,拖入IDA,找到主要加密函数部分

image-20240508181627372

image-20240508181831980

最主要的就是加密部分

image-20240508182418040

对大小写字母分别处理,写EXP把加密逆向

v1 = ['Q', 's', 'w', '3', 's', 'j', '_', 'l', 'z', '4', '_', 'U', 'j', 'w', '@', 'l']
flag = ''
for i in range(len(v1)):
    if 64 < ord(v1[i]) <= 90:
        v1[i] = ord(v1[i]) - 65 + 51
        while v1[i] < 65:
            v1[i] += 26
        v1[i] = chr(v1[i])
    elif 96 < ord(v1[i]) <= 122:
        v1[i] = ord(v1[i]) - 97 + 79
        while v1[i] < 97:
            v1[i] += 26
        v1[i] = chr(v1[i])
    flag += v1[i]
print("flag{"+flag+"}")

得到flag{Cae3ar_th4_Gre@t}

16.rsa

什么是RSA加密

RSA加密是对明文的E次方后除以N求余数的过程

公钥 = (E,N)

密文 = 明文^E modN

RSA解密

对密文进行D次方后除以N的余数就是明文

私钥 = (D,N)

明文 = 密文^D modN

总结

公钥 (E,N)
私钥 (D,N)
密钥对 (E,D,N)
加密 密文=明文^E modN
解密 明文 = 密文^D modN

开始解题

在网站中解析RSA密钥得到公钥

image-20240508195637291

得到E和N

将E拆解成p和q

p = 285960468890451637935629440372639283459

q = 304008741604601924494328155975272418463

写EXP

import gmpy2
import rsa

e = 65537
n = 86934482296048119190666062003494800588905656017203025617216654058378322103517
p = 285960468890451637935629440372639283459
q = 304008741604601924494328155975272418463

lll = (q - 1) * (p - 1)

d = gmpy2.invert(e, lll)

key = rsa.PrivateKey(n, e, int(d), p, q)

with open("C:\\Users\\12611\\Desktop\\re\\rsa\\output\\flag.enc", "rb+") as f:
    f = f.read()
    print(rsa.decrypt(f, key))

得到flag{decrypt_256}

17.[FlareOn4]login

html文件,打开以后直接f12

image-20240511220004631

找到关键加密函数

/[a-zA-Z]/g是正则匹配,匹配字符串中所有的字母

charCodeAt(0)是返回当前字符的Unicode 编码

String.fromCharCode返回Unicode对应的字符串

所以加密的意思就是先匹配大小写字母的上限,然后将字符+13与上限比较,如果超过上限就-26,是一个明显的凯撒加密,向右位移13位

写EXP

a = '[email protected]'
flag = ''
for i in a:
    if 'a' <= i <= 'z':
        i = chr(ord(i) - 13)
        if i < 'a':
            i = chr(ord(i) + 26)
    elif 'A' <= i <= 'Z':
        i = chr(ord(i) - 13)
        if i < 'A':
            i = chr(ord(i) + 26)
    flag += i
print("flag{" + flag + "}")

得到flag{[email protected]}

18.[WUSTCTF2020]level1

用IDA,找主要函数

image-20240515200140244

加密是从文件中读取字符并进行下面操作,

i & 1 //按位运算,i为偶数时为0,i为奇数时为1
<<    //按位操作符,比如0001会变成0010

写个EXP

a = [0, 198, 232, 816, 200, 1536, 300, 6144, 984, 51200, 570, 92160, 1200, 565248, 756, 1474560, 800, 6291456, 1782,
     65536000]
flag = ''
for i in range(1, 20):
    if i & 1:
        flag += chr(a[i] >> i)
    else:
        flag += chr(a[i] // i)
print(flag)

要注意的是题目中i是从1开始的,所以把列表[0]的位置随便加一个字符

19.[GUET-CTF2019]re

查壳,发现有upx壳,用upx官方工具脱壳

拖IDA找到关键函数

image-20240519092410233

一个简单的运算,EXP

from z3.z3 import *

s = Solver()
a1 = [0] * 32
for i in range(32):
    a1[i] = Int('a1[' + str(i) + ']')

s.add(1629056 * a1[0] == 166163712)
s.add(6771600 * a1[1] == 731332800)
s.add(3682944 * a1[2] == 357245568)
s.add(10431000 * a1[3] == 1074393000)
s.add(3977328 * a1[4] == 489211344)
s.add(5138336 * a1[5] == 518971936)
s.add(7532250 * a1[7] == 406741500)
s.add(5551632 * a1[8] == 294236496)
s.add(3409728 * a1[9] == 177305856)
s.add(13013670 * a1[10] == 650683500)
s.add(6088797 * a1[11] == 298351053)
s.add(7884663 * a1[12] == 386348487)
s.add(8944053 * a1[13] == 438258597)
s.add(5198490 * a1[14] == 249527520)
s.add(4544518 * a1[15] == 445362764)
s.add(3645600 * a1[17] == 174988800)
s.add(10115280 * a1[16] == 981182160)
s.add(9667504 * a1[18] == 493042704)
s.add(5364450 * a1[19] == 257493600)
s.add(13464540 * a1[20] == 767478780)
s.add(5488432 * a1[21] == 312840624)
s.add(14479500 * a1[22] == 1404511500)
s.add(6451830 * a1[23] == 316139670)
s.add(6252576 * a1[24] == 619005024)
s.add(7763364 * a1[25] == 372641472)
s.add(7327320 * a1[26] == 373693320)
s.add(8741520 * a1[27] == 498266640)
s.add(8871876 * a1[28] == 452465676)
s.add(4086720 * a1[29] == 208422720)
s.add(9374400 * a1[30] == 515592000)
s.add(5759124 * a1[31] == 719890500)
s.check()
print(s.model())
a1 = [0]*32
a1[23] = 49
a1[26] = 51
a1[24] = 99
a1[11] = 49
a1[0] = 102
a1[30] = 55
a1[21] = 57
a1[1] = 108
a1[16] = 97
a1[18] = 51
a1[3] = 103
a1[13] = 49
a1[20] = 57
a1[7] = 54
a1[31] = 125
a1[29] = 51
a1[10] = 50
a1[4] = 123
a1[2] = 97
a1[8] = 53
a1[12] = 49
a1[25] = 48
a1[14] = 48
a1[28] = 51
a1[22] = 97
a1[17] = 48
a1[15] = 98
a1[19] = 48
a1[9] = 52
a1[5] = 101
a1[27] = 57
a1[6] = 49
for i in range(32):
    print(chr(a1[i]), end='')

其中a[6]作者没给,可以用burp爆破出等于1,图个方便exp直接写了

得到flag{e165421110ba03099a1c039337}

20.CrackRTF

查壳,无壳

ida f5主函数

int __cdecl main_0(int argc, const char **argv, const char **envp)
{
  DWORD v3; // eax
  DWORD v4; // eax
  char Str[260]; // [esp+4Ch] [ebp-310h] BYREF
  int v7; // [esp+150h] [ebp-20Ch]
  char String1[260]; // [esp+154h] [ebp-208h] BYREF
  char Destination[260]; // [esp+258h] [ebp-104h] BYREF

  memset(Destination, 0, sizeof(Destination));
  memset(String1, 0, sizeof(String1));
  v7 = 0;
  printf("pls input the first passwd(1): ");
  scanf("%s", Destination);
  if ( strlen(Destination) != 6 )
  {
    printf("Must be 6 characters!\n");
    ExitProcess(0);
  }
  v7 = atoi(Destination);
  if ( v7 < 100000 )
    ExitProcess(0);
  strcat(Destination, "@DBApp");
  v3 = strlen(Destination);
  sub_40100A((BYTE *)Destination, v3, String1);
  if ( !_strcmpi(String1, "6E32D0943418C2C33385BC35A1470250DD8923A9") )
  {
    printf("continue...\n\n");
    printf("pls input the first passwd(2): ");
    memset(Str, 0, sizeof(Str));
    scanf("%s", Str);
    if ( strlen(Str) != 6 )
    {
      printf("Must be 6 characters!\n");
      ExitProcess(0);
    }
    strcat(Str, Destination);
    memset(String1, 0, sizeof(String1));
    v4 = strlen(Str);
    sub_401019((BYTE *)Str, v4, String1);
    if ( !_strcmpi("27019e688a4e62a649fd99cadaafdb4e", String1) )
    {
      if ( !(unsigned __int8)sub_40100F(Str) )
      {
        printf("Error!!\n");
        ExitProcess(0);
      }
      printf("bye ~~\n");
    }
  }
  return 0;
}
printf("pls input the first passwd(1): ");
  scanf("%s", Destination);
  if ( strlen(Destination) != 6 )
  {
    printf("Must be 6 characters!\n");
    ExitProcess(0);
  }
  v7 = atoi(Destination);
  if ( v7 < 100000 )
    ExitProcess(0);
  strcat(Destination, "@DBApp");

上面这一块说明第一部分是6位,并且把@DBApp接在第一部分后面,第一部分字符串化整形要大于100000

sub_40100A((BYTE *)Destination, v3, String1);

这个是个加密函数,跟进去

int __cdecl sub_401230(BYTE *pbData, DWORD dwDataLen, LPSTR lpString1)
{
  DWORD i; // [esp+4Ch] [ebp-28h]
  char String2[4]; // [esp+50h] [ebp-24h] BYREF
  char v6[20]; // [esp+54h] [ebp-20h] BYREF
  DWORD pdwDataLen; // [esp+68h] [ebp-Ch] BYREF
  HCRYPTHASH phHash; // [esp+6Ch] [ebp-8h] BYREF
  HCRYPTPROV phProv; // [esp+70h] [ebp-4h] BYREF
    
if ( !CryptAcquireContextA(&phProv, 0, 0, 1u, 0xF0000000) )
    return 0;
  if ( CryptCreateHash(phProv, 0x8004u, 0, 0, &phHash) )
  {
    if ( CryptHashData(phHash, pbData, dwDataLen, 0) )
    {
      CryptGetHashParam(phHash, 2u, (BYTE *)v6, &pdwDataLen, 0);
      *lpString1 = 0;
      for ( i = 0; i < pdwDataLen; ++i )
      {
        wsprintfA(String2, "%02X", (unsigned __int8)v6[i]);
        lstrcatA(lpString1, String2);
      }
      CryptDestroyHash(phHash);
      CryptReleaseContext(phProv, 0);
      return 1;
    }
    else
    {
      CryptDestroyHash(phHash);
      CryptReleaseContext(phProv, 0);
      return 0;
    }
  }
  else
  {
    CryptReleaseContext(phProv, 0);
    return 0;
  }
}

有很多不知道的函数,查询后是哈希加密函数

学习了一下hashlib库的用法,根据0x8004确定加密方式是sha1

因为有位数,又得出六位都是数字,所以直接爆破

import hashlib

a = '@DBApp'
for i in range(100000, 1000000):
    b = str(i) + a
    c = hashlib.sha1(b.encode('utf-8'))
    d = c.hexdigest()
    if d == "6e32d0943418c2c33385bc35a1470250dd8923a9":
        print(b)
        break
 '''
 123321@DBApp
 '''

然后看接下来的部分

 printf("pls input the first passwd(2): ");
    memset(Str, 0, sizeof(Str));
    scanf("%s", Str);
    if ( strlen(Str) != 6 )
    {
      printf("Must be 6 characters!\n");
      ExitProcess(0);
    }
    strcat(Str, Destination);
    memset(String1, 0, sizeof(String1));
    v4 = strlen(Str);
    sub_401019((BYTE *)Str, v4, String1);

依然是六位,然后进行了拼接操作,然后依然是进行hash加密,但是没有可用条件了

继续往下看,在比较后还有个sub_40100F函数,跟进

char __cdecl sub_4014D0(LPCSTR lpString)
{
  LPCVOID lpBuffer; // [esp+50h] [ebp-1Ch]
  DWORD NumberOfBytesWritten; // [esp+58h] [ebp-14h] BYREF
  DWORD nNumberOfBytesToWrite; // [esp+5Ch] [ebp-10h]
  HGLOBAL hResData; // [esp+60h] [ebp-Ch]
  HRSRC hResInfo; // [esp+64h] [ebp-8h]
  HANDLE hFile; // [esp+68h] [ebp-4h]

  hFile = 0;
  hResData = 0;
  nNumberOfBytesToWrite = 0;
  NumberOfBytesWritten = 0;
  hResInfo = FindResourceA(0, (LPCSTR)0x65, "AAA");
  if ( !hResInfo )
    return 0;
  nNumberOfBytesToWrite = SizeofResource(0, hResInfo);
  hResData = LoadResource(0, hResInfo);
  if ( !hResData )
    return 0;
  lpBuffer = LockResource(hResData);
  sub_401005(lpString, (int)lpBuffer, nNumberOfBytesToWrite);
  hFile = CreateFileA("dbapp.rtf", 0x10000000u, 0, 0, 2u, 0x80u, 0);
  if ( hFile == (HANDLE)-1 )
    return 0;
  if ( !WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, &NumberOfBytesWritten, 0) )
    return 0;
  CloseHandle(hFile);
  return 1;
}

没见过的函数

HRSRC FindResourceA(
  HMODULE hModule,
  LPCSTR  lpName,
  LPCSTR  lpType
);
FindResourceA function
Determines the location of a resource with the specified type and name in the specified module.
确定具有指定类型和名称的资源在指定模块中的位置。
hModule:处理包含资源的可执行文件的模块。NULL值则指定模块句柄指向操作系统通常情况下创建最近过程的相关位图文件。
lpName:指定资源名称。
lpType:指定资源类型。
返回值:如果函数运行成功,那么返回值为指向被指定资源信息块的句柄。为了获得这些资源,将这个句柄传递给LoadResource函数。如果函数运行失败,则返回值为NULL。

SizeofResource表示该函数返回指定资源的字节数大小。

LoadResource
检索一个句柄,该句柄可用于获取指向内存中指定资源的第一个字节的指针。

三个函数,查找字符,计算大小,返回指定资源的第一个字节的指针

用resource hacker看这个文件

image-20240605211714138

看不出什么信息,继续往下看,有个sub_401005函数

unsigned int __cdecl sub_401420(LPCSTR lpString, int a2, unsigned int a3)
{
  unsigned int result; // eax
  unsigned int i; // [esp+4Ch] [ebp-Ch]
  unsigned int v5; // [esp+54h] [ebp-4h]

  v5 = lstrlenA(lpString);
  for ( i = 0; ; ++i )
  {
    result = i;
    if ( i >= a3 )
      break;
    *(_BYTE *)(i + a2) ^= lpString[i % v5];
  }
  return result;
}

就是资源中的每一个字符与密码循环异或

跳出后生成一个rtf文件,将异或后的结果写进去

所以这个资源的前六位与密码异或后的结果就是rtf文件的前六位

而rtf文件前六位是'{\rtf1'

所以反向异或

A = [0x05, 0x7D, 0x41, 0x15, 0x26, 0x01]
a = ''
for i in A:
    a += chr(int(i))
rtf = "{\\rtf1"
for i in range(0, 6):
    print(chr(ord(a[i]) ^ ord(rtf[i])), end='')
'''
~!3a@0
'''

得到密码,将两次密码输入进去后,得到rtf文件

Flag{N0_M0re_Free_Bugs}

21.[WUSTCTF2020]level2

查壳,有upx壳,用官方工具脱壳

然后ida

image-20240520183707017

查到字符串得到flag

22.[SUCTF2019]SignIn

无壳,拖ida

通过字符串找到关键函数

image-20240520190808202

rsa加密,推测十六进制串为密文,下一个十进制串为n

在网站分解p和q

image-20240520191027214

要素齐全,写EXP

import gmpy2
import binascii
c = 0xad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35
n = 103461035900816914121390101299049044413950405173712170434161686539878160984549
e = 65537
p = 282164587459512124844245113950593348271
q = 366669102002966856876605669837014229419
d = gmpy2.invert(e, (p-1)*(q-1))
m = gmpy2.powmod(c, d, n)

print(binascii.unhexlify(hex(m)[2:]).decode(encoding='utf-8'))

得到flag{Pwn_@_hundred_years}

23.[ACTF新生赛2020]usualCrypt

IDA找主函数

image-20240521193737422

先看下面这个关键函数

image-20240521194414274

跳转

image-20240521194459833

image-20240521194514471

根据经验是一个base64加密,但是开头多进行了一个函数

image-20240521194629876

image-20240521194646409

进入字符串以后是以下两个字符串,刚开始还疑惑了一会,第一个字符串并没有15那么长怎么运算,后来发现 内存空间本身就是连在一起的,伪代码只是为了好表示字符的起点将字符串分割成两个部分,实际运算还是一个空间。

所以得知上面函数就是i从6到14,a[i]与a[i+10]互换

image-20240520202253119

解决了这个函数,再看结尾的返回函数

image-20240521195054145

image-20240521195114462

很明显是个大小写互换函数

随后就是比较

image-20240521195307496

image-20240521195351856

然后逆推flag就好,写EXP

import base64

a = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
flag = ''
dict = {}
for i in range(len(a)):
    dict[a[i]] = a[i]
for i in range(6, 15):
    dict[a[i]], dict[a[i + 10]] = dict[a[i + 10]], dict[a[i]]
s = 'zMXHz3TIgnxLxJhFAdtZn2fFk3lYCrtPC2l9'.swapcase()
for i in range(len(s)):
    flag += dict[s[i]]
flag = base64.b64decode(flag)
print(flag)

得到flag{bAse64_h2s_a_Surprise}

24.[HDCTF2019]Maze

查壳,upx壳,脱

ida,题目maze,迷宫题

image-20240521195742113

进来看见这个,网上了解一下,这个是花指令导致的反汇编错误

解决方法:将call这一行第一个字节改为90(就是nop)

image-20240521200005257

image-20240521200018516

把红色部分选中摁P,然后f5

image-20240521200141949

flag是一个14位的字符串,wasd就是移动

image-20240521200351438

初始位置(7,0)然后到(5,-4)

字符串找迷宫

image-20240521200442914

发现是70个字符,根据初始位置猜是个10*7的迷宫

image-20240521202900062

flag{ssaaasaassdddw}

25.[MRCTF2020]Xor

拖入ida,发现反汇编错误

解决方法:找到报错地址,发现是个call函数,把跳转过去的函数先反汇编成函数,然后再回来f5就能反汇编了

image-20240522192346914

很简单一个函数,就是把输入和角标异或与给的字符串比较

image-20240522192458823

写EXP

byte_41EA08 = 'MSAWB~FXZ:J:`tQJ"N@ bpdd}8g'

flag = ''

for i in range(len(byte_41EA08)):
    flag += chr(i ^ ord(byte_41EA08[i]))

print(flag)

其实这道题也可以直接看汇编

image-20240522192619060

开头这个框里能看出这个push的4212c0就是输入的字符串

image-20240522193224569

这个操作一直在edx自增,test也是在找输入字符串的结尾,因为ecx存的是edx+1的地址,所以sub以后edx就是字符串长度,可以看到是1B

image-20240522193435035

进行eax清零操作后,把每个字符与角标(al)进行异或然后和给定字符串比较,再进行eax自增,如果比较不相等就跳出错误信息,否则到了字符串长度后就跳出正确信息。

得到flag{@_R3@1ly_E2_R3verse!}

26.[MRCTF2020]hello_world_go

go语言,放ida,查字符串,发现特别多,ctrl+f搜flag

image-20240522194658107

一眼真

27.[2019红帽杯]easyRE

放ida,第一步查字符串

image-20240522201423376

上来就是这个,base64没跑,开始破解,结果发现是10次base64加密

得到一个网址https://bbs.pediy.com/thread-254172.htm

名为主动防御,看完发现,应该是被错误引导了

后面又找到个函数加密

image-20240605184833426

从v12和v13、v14的地址来看,这三个空间是连在一起的,加密也是简单的异或

写个码解一下

a = 'Iodl>Qnb(ocy\x7Fy.i\x7Fd`3w}wek9{iy=~yL@EC'
a = list(a)
flag = ''
for i in range(len(a)):
    a[i] = chr(ord(a[i]) ^ i)
flag = ''.join(a)
print(flag)

'''
Info:The first four chars are `flag`
'''

结果是告诉你前四个字符是flag,又找到了只有一点用的信息。

后面在很长的base64加密后面的交叉引用的地方找到了一个字符串

image-20240605192521864

跟进去是这样的image-20240605193139875

前面看不明白,但是后面有个v4=v1,v1还是int8,也就是一个字节

根据之前的推测,以及这个函数的加密部分,这个v1就是个四字节的key,四个字节应该是分别与key异或得到flag这四个字符,然后反向异或就得到key,加密就是与key中字符循环异或

a = [0x40, 0x35, 0x20, 0x56, 0x5D, 0X18, 0X22, 0X45, 0X17, 0X2F, 0X24, 0X6E, 0X62, 0X3C, 0X27, 0X54, 0X48, 0X6C, 0X24,
     0X6E, 0X72, 0X3C, 0X32, 0X45, 0x5B]
v = [0] * 4
flag = ''
v[0] = a[0] ^ ord('f')
v[1] = a[1] ^ ord('l')
v[2] = a[2] ^ ord('a')
v[3] = a[3] ^ ord('g')
for i in range(len(a)):
    a[i] = chr(a[i] ^ v[i % 4])
flag = ''.join(a)
print(flag)
'''
flag{Act1ve_Defen5e_Test}
'''

标签:buuctf,函数,add,a1,re,flag,wp,字符串,ord
From: https://www.cnblogs.com/yee-l/p/18233898

相关文章

  • PHP_CMS系统代码解析-wordpress
          WordPress是使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站。也可以把WordPress当作一个内容管理系统(CMS)来使用。  模板基本文件 使用模板通过函数的调用,让模板之间形成完整的整体。style.css:CSS(样式表)......
  • 【DRF-12】rest-framework之路由
    路由控制介绍:我们之前一直接触的路由是最基本的形式,就是我们下面介绍的第一种方式的自定义路由,无论是FBV还是CBV,都可以使用这用方式来设置路由来设定请求来的时候对应响应视图的函数或者视图类当我们使用封装了的视图类处理代码的时候,我们就可以使用对应的半自动路由......
  • Day1 学习笔记及成果---MapReduce实现手机流量统计分析
    Day1学习笔记及成果—MapReduce实现手机流量统计分析题目统计每个手机号上行流量和、下行流量和、总流量和(上行流量和+下行流量和),并且:将统计结果按照手机号的前缀进行区分,并输出到不同的输出文件中去。13*==>…15*==>…other==>…其中,access.log数据文件部分......
  • Day2 学习笔记及成果---基于MapReduce项目实现中所遇到的问题及解决方法
    Day2学习笔记及成果—基于MapReduce项目实现中所遇到的问题及解决方法问题一:主机和虚拟机互相能ping通,主机能ping通外网,虚拟机不能ping通外网。解决方案:可能的错误原因是网关设置有问题,虚拟机的网关应该和自己的网关一直,自己的网关可在编辑-虚拟网络设置中查看。首先执......
  • 基于调用C语言作为reference_model的UVM对全加器的验证
    代码来自于,本篇文章只对其中的细节做探讨UVM的基本教程-CSDN博客首先DUT为加法器,但是舒服不仅是加数和被加数,还有ready和valid,输出也不止是和,还有valid和ready。valid代表数据有效,ready表示已经准备好发送或者接收。加法器的设计语言中,共有三个状态,INITIAL/WAIT/SEND,rst为1......
  • Body AdvancedBrep Geometry
    BodyAdvancedBrepGeometryBodyBrepGeometry是通过边界表示模型(包括NURBS)表示产品的三维形状。应使用保持该几何表示的IfcShapeResentation的以下属性值:IfcShapeRepresentation.RepresentationIdentifier ='Body'IfcShapeRepresentation.RepresentationType ='Advanced......
  • mind-sever 搭建环境 readme
    modelfoundry-serverinstalldepsswagWeneedswagtogenerategoinstallgithub.com/swaggo/swag/cmd/swag@latestdockerfollowthedocscomposefollowthedocslocal-devBeforestarting:installdockercomposegenerateyourgithubtokenThenyoucanst......
  • 实验15-使用RESNET完成图像分类
    model.py#-*-coding:utf-8-*-"""author:ZhouChendatetime:2019/6/259:10desc:实现模型"""fromkeras.modelsimportModelfromkeras.layersimportConv2D,MaxPooling2D,BatchNormalization,Flatten,Input,ZeroPadding2D......
  • HiPPO: Recurrent Memory with Optimal Polynomial Projections
    目录概Motivation代码GuA.,DaoT.,ErmonS.,RudraA.andReC.HiPPO:Recurrentmemorywithoptimalpolynomialprojections.NIPS,2021.概看下最近很火的Mamba的前身.本文其实主要介绍的是一个如何建模历史信息在正交基上的稀疏的变化情况.Motivation对于......
  • [Paper Reading] UniAD: Planning-oriented Autonomous Driving
    Planning-orientedAutonomousDrivinglink时间:23.03机构:ShanghaiAILaboratory&&SenseTimeTL;DR将感知、预测以及规划模块整合成为一个E2E的网络结构。该工作是CVPR2023的BestPaper。MethodTrackFormer可以参考MOTR来理解,MapFormer可参考来理解。MapFormer主......