BUUCTF reverse wp 96 - 100

[MRCTF2020]Shit

给了源码, 修改一下decode, 可以解出flag

cpp 复制代码
// Damn.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<Windows.h>
#include<iostream>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
int map[100], c = 2;
int key[7] = { 'b', 'k', 'd', 'c', 'e', 'w' };
unsigned int ks[6] = { 0x8c2c133a, 0xf74cb3f6, 0xfedfa6f2, 0xab293e3b, 0x26cf8a2a, 0x88a1f279 };//{0x8c2cecc5,0xf74cb3f6,0xfedf590d,0xab293e3b,0x26cf75d5,0x88a1f279};
FARPROC proc = NULL;
int initHook()
{
	HMODULE hModule = LoadLibraryA("Kernel32.dll");
	if (hModule)
	{
		proc = GetProcAddress(hModule, "IsDebuggerPresent");
		if (proc == NULL)
			return -1;
	}
	return 0;
}
PDWORD update()
{
	if (initHook() != 0)
		exit(-1);
	HANDLE hProcess = GetModuleHandle(NULL);
	PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)hProcess;
	PIMAGE_NT_HEADERS nt_header = (PIMAGE_NT_HEADERS)(dos_header->e_lfanew + (DWORD)hProcess);
	IMAGE_OPTIONAL_HEADER* opt_header = &(nt_header->OptionalHeader);
	PIMAGE_IMPORT_DESCRIPTOR iat = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)hProcess + opt_header->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
	while (iat->FirstThunk)
	{
		PIMAGE_THUNK_DATA data = (PIMAGE_THUNK_DATA)(iat->FirstThunk + (DWORD)hProcess);
		while (data->u1.Function)
		{
			if (IMAGE_SNAP_BY_ORDINAL(data->u1.AddressOfData))
			{
				data++;
				continue;
			}
			if ((DWORD)proc == data->u1.Function)
				return &data->u1.Function;
			data++;
		}
		iat++;
	}
	return NULL;
}
PDWORD table_addr = NULL;
int writeAddr(DWORD addr)
{
	if (table_addr == NULL)
		table_addr = update();
	DWORD dwOldProtect;
	MEMORY_BASIC_INFORMATION mbi_thunk;
	VirtualQuery(table_addr, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION));
	VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, PAGE_READWRITE, &mbi_thunk.Protect);
	*table_addr = (DWORD)addr;
	VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, mbi_thunk.Protect, &dwOldProtect);
	return 0;
}
bool WINAPI CallBackProc()
{
	writeAddr((DWORD)proc);
	map[0] = 2; c--;
	key[0] = 'a';
	key[1] = 'k';
	key[2] = 'e';
	key[3] = 'y';
	key[4] = 'e';
	key[5] = 'z';
	if (IsDebuggerPresent())
	{
		MessageBoxW(NULL, L"U R Using Debugger!", L"U Suck!", MB_OK);
		return true;
	}
	return false;
}
void sleep()
{

}
int checkDebug()
{
	if (*((unsigned char *)(*(DWORD*)(__readfsdword(0x18) + 0x30)) + 0x2))
		sleep();
	return 0;
}
int doit = writeAddr((DWORD)CallBackProc), dd = checkDebug();
bool encode(char* ur_flag)
{
	unsigned int k = 0, bk = 0;
	for (int i = 0; i < strlen(ur_flag); i += 4)
	{
		k = (((int)ur_flag[i]) << 24) | (((int)ur_flag[i + 1]) << 16) | (((int)ur_flag[i + 2]) << 8) | ((int)ur_flag[i + 3]);
		k = (k >> key[i / 4]) | (k << (32 - key[i / 4]));
		_asm
		{
			call sub2
				_emit 0xEB
				jmp label2
			sub2 :
			add dword ptr[esp], 1
				retn
			label2 :
		}
		k = ((~(k >> 16)) & 0x0000ffff) | (k << 16);
		k = (1 << key[i / 4]) ^ k;
		_asm
		{
			call sub7
				_emit 0xE8
				jmp label7
			sub7 :
			add dword ptr[esp], 1
				retn
			label7 :
		}
		if (i > 0)
			k ^= bk;
		bk = k;
		if (k != ks[i / 4])
			return false;
	}
	return true;
}
void genKey()
{
	int len = 20, keylen = 6, maxium = 0;
	int before;
	_asm
	{
		call sub1
			_emit 0xE8
			jmp label1
		sub1 :
		add dword ptr[esp], 1
			retn
		label1 :
	}
	srand(time(NULL));
	for (int i = 1; i <= len; i++)
	{
		map[i] = map[i - 1] + rand() % 5;
		_asm
		{
			call sub3
				_emit 0xE8
				jmp label3
			sub3 :
			add dword ptr[esp], 1
				retn
			label3 :
		}
		maxium = maxium > map[i] ? maxium : map[i];
	}
	_asm
	{
		call sub4
			_emit 0xE8
			jmp label4
		sub4 :
		add dword ptr[esp], 1
			retn
		label4 :
	}
	before = time(NULL);
	_asm
	{
		call sub5
			_emit 0xE8
			jmp label5
		sub5 :
		add dword ptr[esp], 1
			retn
		label5 :
	}
	for (int i = 0; i < keylen; i++)
	{
		int step = 0;
		long long t = time(NULL);
		int delta = t - before;
		_asm
		{
			call sub6
				_emit 0xE8
				jmp label6
			sub6 :
			add dword ptr[esp], 1
				retn
			label6 :
		}
		if (delta > maxium)
			return;

		for (int j = 0; j <= len; j++)
			if (delta <= map[j])
			{
				step = map[j];
				_asm
				{
					call sub8
						_emit 0xE8
						jmp label8
					sub8 :
					add dword ptr[esp], 1
						retn
					label8 :
				}
				break;
			}
		_asm
		{
			call sub9
				_emit 0xE8
				jmp label9
			sub9 :
			add dword ptr[esp], 1
				retn
			label9 :
		}
		key[i] = (key[i] * c + step + i * 3) % 32;
		_asm
		{
			call sub10
				_emit 0xE8
				jmp label10
			sub10 :
			add dword ptr[esp], 1
				retn
			label10 :
		}
		before = t;
	}
}

void decode()
{
	unsigned int k[] = { 0x03, 0x10, 0x0d, 0x04, 0x13, 0x0b };
	for (int i = 5; i >= 0; i--) {
		if (i > 0)
			ks[i] ^= ks[i - 1];

		ks[i] = (1 << k[i]) ^ ks[i];
		ks[i] = ((ks[i] >> 16)) | ((~(ks[i] << 16)) & 0xffff0000);
		ks[i] = ((ks[i] << k[i])) | (ks[i] >> (32 - k[i]));
		printf("%X\n", ks[i]);
	}
}

int main()
{
	char ur_flag[50];
	cout << "please input your flag:" << endl;
	cin >> ur_flag;
	//if (IsDebuggerPresent())
	//{
	//	cout << "U suck! 233333" << endl;
	//	Sleep(2000);
	//	exit(0);
	//}
	if (strlen(ur_flag) != 24)
	{
		cout << "Wrong!" << endl;
		Sleep(2000);
		exit(0);
	}
	genKey();
	bool flag = encode(ur_flag);
	decode();
	//if (flag)
	//{
	//	cout << "U did it!" << endl << "GJ!" << endl;
	//	system("pause");
	//	exit(0);
	//}
	//cout << "Wrong!" << endl;
	//Sleep(2000);
	getchar();
	getchar();
	return 0;
}

拼接起来

py 复制代码
from Crypto.Util.number import long_to_bytes


flags = [
    0x6573747D,
    0x6F725F74,
    0x72655F66,
    0x6132795F,
    0x7B615F33,
    0x666C6167
]

flag = b''
for i in range(len(flags) - 1, -1, -1):
    flag += long_to_bytes(flags[i])

print(flag)

Dig the way

cpp 复制代码
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // ebx
  int v5; // ebx
  char v7_20[20]; // [esp+1Ch] [ebp-48h] BYREF
  int v7[3]; // [esp+30h] [ebp-34h] BYREF
  size_t v8; // [esp+3Ch] [ebp-28h]
  int v9; // [esp+40h] [ebp-24h]
  int v10; // [esp+44h] [ebp-20h]
  int func_ptr[3]; // [esp+48h] [ebp-1Ch]
  int v12; // [esp+54h] [ebp-10h]
  size_t length; // [esp+58h] [ebp-Ch]
  FILE *file_ptr; // [esp+5Ch] [ebp-8h]

  __main();
  func_ptr[0] = (int)func0;
  func_ptr[1] = (int)func1;
  func_ptr[2] = (int)func2;
  v7[0] = 0;
  v7[1] = 1;
  v7[2] = 2;
  v8 = 3;
  v9 = 3;
  v10 = 4;
  file_ptr = fopen("data", "rb");
  if ( !file_ptr )
    return -1;
  fseek(file_ptr, 0, 2);
  length = ftell(file_ptr);
  fseek(file_ptr, 0, 0);
  v12 = ftell(file_ptr);
  if ( v12 )
  {
    puts("something wrong");
    return 0;
  }
  else
  {
    for ( i = 0; i < (int)length; ++i )
    {
      v4 = i;
      v7_20[v4] = fgetc(file_ptr);
    }
    if ( strlen(v7_20) <= length )
    {
      length = v8;
      i = 0;
      v12 = v10;
      while ( i <= 2 )
      {
        v5 = i + 1;
        v7[v5] = ((int (__cdecl *)(int *, int, int))func_ptr[i])(v7, v9, v10);// get v9,v10,v11
        v9 = ++i;
        v10 = i + 1;
      }
      if ( v8 )
      {
        return -1;
      }
      else
      {
        get_key(length, v12);
        system("PAUSE");
        return 0;
      }
    }
    else
    {
      return -1;
    }
  }
}

signed int __cdecl func0(int a1, int a2, int a3)
{
  int temp; // [esp+Ch] [ebp-4h]

  temp = *(_DWORD *)(4 * a2 + a1);
  *(_DWORD *)(a1 + 4 * a2) = *(_DWORD *)(4 * a3 + a1);
  *(_DWORD *)(a1 + 4 * a3) = temp;
  return 1;
}

unsigned int __cdecl func1(int a1, int a2, int a3)
{
  return abs32(*(_DWORD *)(4 * a2 + a1) + *(_DWORD *)(4 * a3 + a1))
       - abs32(*(_DWORD *)(4 * a3 + a1))
       - abs32(*(_DWORD *)(4 * a2 + a1))
       + 2;
}

// return v11
unsigned int __cdecl func2(int a1, int a2, int a3)
{
  return abs32(*(_DWORD *)(4 * a3 + a1))
       - abs32(*(_DWORD *)(4 * a3 + a1) + *(_DWORD *)(4 * a2 + a1))
       + abs32(*(_DWORD *)(4 * a2 + a1))
       + 2;
}

func0相当于X <--> Y
func1相当于|X + Y| - |X| - |Y| + 2
func2相当于|X| + |Y| - |X + Y| + 2

目标是程序读入data后, 使得func2的返回值为0, 但是不可能(因为数学上|X| + |Y| >= |X + Y|), 不过func1的值可以等于0, 所以这里先用func0交换func1和func2的函数指针, 这样func1返回0时, 就可以进入打印flag的函数get_key

构造data

(这道题更像PWN

[CFI-CTF 2018]powerPacked

UPX脱壳后拖入IDA

cpp 复制代码
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int i; // [sp+8h] [-58h]
  _BYTE v5[32]; // [sp+10h] [-50h] BYREF
  char v6[24]; // [sp+30h] [-30h] BYREF
  int v7; // [sp+48h] [-18h]
  const char **v8; // [sp+4Ch] [-14h]

  v7 = argc;
  v8 = argv;
  strcpy(v6, "EHK}kanqxgarqygtre");
  printf("Insert password : ", argv, envp);
  _isoc99_scanf("%31s", v5);
  for ( i = 0; i < 21; ++i )
    v6[i] -= 2;
  if ( strcmp(v5, v6) )
    puts("Wrong password.");
  else
    puts("Password is correct. Submit this as the flag.");
  return 0;
}

给定字符串, 每个字符-2, 直接逆

py 复制代码
s = 'EHK}kanqxgarqygtre'

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

print(flag)

APK逆向, JEB打开, 四处游走一下搜索关键代码

java 复制代码
package com.example.blink;

import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Base64;
import android.widget.ImageView;

public class r2d2 extends AppCompatActivity {
    @Override  // android.support.v7.app.AppCompatActivity
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setContentView(0x7F0A001C);  // layout:activity_r2d2
        ImageView image = (ImageView)this.findViewById(0x7F080054);  // id:imageView
        byte[] arr_b = Base64.decode(" data:image/jpeg;base64,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".split(",")[1], 0);
        image.setImageBitmap(BitmapFactory.decodeByteArray(arr_b, 0, arr_b.length));
    }
}

这里的base64很长, 解码看有没有重要信息, 仔细看发现是图片编码为base64

[SUCTF2019]hardcpp

一眼控制流平坦化, deflat一波, 脚本链接

cpp 复制代码
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  int v4; // eax
  int v5; // ecx
  int v6; // eax
  int v7; // eax
  int v8; // eax
  int v9; // eax
  int v10; // eax
  char v11; // al
  char v12; // al
  char v13; // al
  char v14; // al
  char v15; // al
  int v16; // ecx
  int v17; // eax
  int v18; // eax
  int v19; // eax
  int v20; // eax
  int v21; // eax
  int v22; // ecx
  char v24; // al
  char v25; // al
  char v26; // al
  char v27; // al
  int v28; // [rsp+9Ch] [rbp-94h]
  char v29[8]; // [rsp+A0h] [rbp-90h] BYREF
  char v30[8]; // [rsp+A8h] [rbp-88h] BYREF
  char v31[8]; // [rsp+B0h] [rbp-80h] BYREF
  char v32[8]; // [rsp+B8h] [rbp-78h] BYREF
  char v33[8]; // [rsp+C0h] [rbp-70h] BYREF
  char v34[7]; // [rsp+C8h] [rbp-68h] BYREF
  char v35; // [rsp+CFh] [rbp-61h]
  int v36; // [rsp+D0h] [rbp-60h]
  int v37; // [rsp+D4h] [rbp-5Ch]
  int v38; // [rsp+D8h] [rbp-58h]
  int v39; // [rsp+DCh] [rbp-54h]
  char s; // [rsp+E0h] [rbp-50h] BYREF
  char v41[23]; // [rsp+E1h] [rbp-4Fh] BYREF
  char v42[8]; // [rsp+F8h] [rbp-38h] BYREF
  char v43[8]; // [rsp+100h] [rbp-30h] BYREF
  char v44[8]; // [rsp+108h] [rbp-28h] BYREF
  char v45[4]; // [rsp+110h] [rbp-20h] BYREF
  int v46; // [rsp+114h] [rbp-1Ch]
  const char **v47; // [rsp+118h] [rbp-18h]
  int v48; // [rsp+120h] [rbp-10h]
  int v49; // [rsp+124h] [rbp-Ch]
  int v50; // [rsp+128h] [rbp-8h]
  bool v51; // [rsp+12Eh] [rbp-2h]
  bool v52; // [rsp+12Fh] [rbp-1h]

  v49 = 0;
  v48 = argc;
  v47 = argv;
  v46 = time(0LL);
  puts("func(?)=\"01abfc750a0c942167651c40d088531d\"?");
  s = getchar();
  fgets(v41, 21, stdin);
  v39 = time(0LL);
  v38 = v39 - v46;
  v50 = v39 - v46;
  v28 = 1883240069;
  while ( 1 )
  {
    while ( 1 )
    {
      while ( 1 )
      {
        while ( 1 )
        {
          while ( 1 )
          {
            while ( 1 )
            {
              while ( 1 )
              {
                while ( 1 )
                {
                  while ( 1 )
                  {
                    while ( 1 )
                    {
                      while ( 1 )
                      {
                        while ( 1 )
                        {
                          while ( 1 )
                          {
                            while ( v28 == -2090540314 )
                            {
                              v35 = v38 ^ v41[v36 - 1];
                              v34[0] = main::$_0::operator()(v44, (unsigned int)v35);
                              v33[0] = main::$_1::operator()(v42, (unsigned int)*(&s + v38 + v36 - 1));
                              v11 = main::$_1::operator() const(char)::{lambda(int)#1}::operator()(v33, 7LL);
                              v35 = main::$_0::operator() const(char)::{lambda(char)#1}::operator()(
                                      v34,
                                      (unsigned int)v11);
                              v32[0] = main::$_2::operator()(v45, (unsigned int)v35);
                              v31[0] = main::$_2::operator()(v45, (unsigned int)*(&s + v38 + v36 - 1));
                              v12 = main::$_2::operator() const(char)::{lambda(char)#1}::operator()(v31, 18LL);
                              v30[0] = main::$_3::operator()(v43, (unsigned int)v12);
                              v13 = main::$_3::operator() const(char)::{lambda(char)#1}::operator()(v30, 3LL);
                              v29[0] = main::$_0::operator()(v44, (unsigned int)v13);
                              v14 = main::$_0::operator() const(char)::{lambda(char)#1}::operator()(v29, 2LL);
                              v15 = main::$_2::operator() const(char)::{lambda(char)#1}::operator()(
                                      v32,
                                      (unsigned int)v14);
                              v16 = 1299792285;
                              v35 = v15;
                              v52 = enc[v36 - 1] != v15;
                              if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
                                v16 = -424557443;
                              v28 = v16;
                            }
                            if ( v28 != -1957245689 )
                              break;
                            v28 = 1587023630;
                          }
                          if ( v28 != -1884297895 )
                            break;
                          v28 = -984930794;
                          puts("You win");
                        }
                        if ( v28 != -1852837876 )
                          break;
                        v18 = 1375414539;
                        if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
                          v18 = 1154698238;
                        v28 = v18;
                      }
                      if ( v28 != -1220297252 )
                        break;
                      v21 = -1884297895;
                      if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
                        v21 = -984930794;
                      v28 = v21;
                    }
                    if ( v28 != -984930794 )
                      break;
                    puts("You win");
                    v22 = -1884297895;
                    if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
                      v22 = 456293525;
                    v28 = v22;
                  }
                  if ( v28 != -740226431 )
                    break;
                  v4 = 2137069843;
                  if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
                    v4 = 739060228;
                  v28 = v4;
                }
                if ( v28 == -459161563 )
                  exit(0);
                if ( v28 != -424557443 )
                  break;
                v17 = 1856799435;
                if ( v52 )
                  v17 = -1852837876;
                v28 = v17;
              }
              if ( v28 != -350248402 )
                break;
              v28 = -55540564;
            }
            if ( v28 != -294402024 )
              break;
            v6 = 1721328217;
            if ( v51 )
              v6 = -459161563;
            v28 = v6;
          }
          if ( v28 != -226137905 )
            break;
          v28 = 24093646;
        }
        if ( v28 != -55540564 )
          break;
        v20 = -350248402;
        if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
          v20 = -226137905;
        v28 = v20;
      }
      if ( v28 != 24093646 )
        break;
      ++v36;
      v28 = 1587023630;
    }
    if ( v28 == 456293525 )
      break;
    switch ( v28 )
    {
      case 506113758:
        puts("Let the silent second hand take the place of my doubt...");
        exit(0);
      case 623475433:
        v36 = 1;
        v28 = 1132336453;
        break;
      case 739060228:
        v37 = strlen(&s);
        v51 = v37 != 21;
        v5 = 2137069843;
        if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
          v5 = -294402024;
        v28 = v5;
        break;
      case 1011555671:
        v10 = 1299792285;
        if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
          v10 = -2090540314;
        v28 = v10;
        break;
      case 1132336453:
        v8 = 623475433;
        v36 = 1;
        if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
          v8 = -1957245689;
        v28 = v8;
        break;
      case 1154698238:
        exit(0);
      case 1299792285:
        v35 = v38 ^ v41[v36 - 1];
        v34[0] = main::$_0::operator()(v44, (unsigned int)v35);
        v33[0] = main::$_1::operator()(v42, (unsigned int)*(&s + v38 + v36 - 1));
        v24 = main::$_1::operator() const(char)::{lambda(int)#1}::operator()(v33, 7LL);
        v35 = main::$_0::operator() const(char)::{lambda(char)#1}::operator()(v34, (unsigned int)v24);
        v32[0] = main::$_2::operator()(v45, (unsigned int)v35);
        v31[0] = main::$_2::operator()(v45, (unsigned int)*(&s + v38 + v36 - 1));
        v25 = main::$_2::operator() const(char)::{lambda(char)#1}::operator()(v31, 18LL);
        v30[0] = main::$_3::operator()(v43, (unsigned int)v25);
        v26 = main::$_3::operator() const(char)::{lambda(char)#1}::operator()(v30, 3LL);
        v29[0] = main::$_0::operator()(v44, (unsigned int)v26);
        v27 = main::$_0::operator() const(char)::{lambda(char)#1}::operator()(v29, 2LL);
        v35 = main::$_2::operator() const(char)::{lambda(char)#1}::operator()(v32, (unsigned int)v27);
        v28 = -2090540314;
        break;
      case 1375414539:
        exit(0);
      case 1587023630:
        v9 = -1220297252;
        if ( v36 < 21 )
          v9 = 1011555671;
        v28 = v9;
        break;
      case 1721328217:
        v7 = 623475433;
        if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
          v7 = 1132336453;
        v28 = v7;
        break;
      case 1856799435:
        v19 = -350248402;
        if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
          v19 = -55540564;
        v28 = v19;
        break;
      case 1883240069:
        v3 = -740226431;
        if ( v50 > 0 )
          v3 = 506113758;
        v28 = v3;
        break;
      default:
        v37 = strlen(&s);
        v28 = 739060228;
        break;
    }
  }
  return 0;
}

得到去平坦化的代码, 勉强可以读了

cpp 复制代码
int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v3; // al
  char v4; // al
  char v5; // al
  char v6; // al
  char v8; // al
  char v9; // al
  char v10; // al
  char v11; // al
  char v12[8]; // [rsp+A0h] [rbp-90h] BYREF
  char v13[8]; // [rsp+A8h] [rbp-88h] BYREF
  char v14[8]; // [rsp+B0h] [rbp-80h] BYREF
  char v15[8]; // [rsp+B8h] [rbp-78h] BYREF
  char v16[8]; // [rsp+C0h] [rbp-70h] BYREF
  char v17[7]; // [rsp+C8h] [rbp-68h] BYREF
  char v18; // [rsp+CFh] [rbp-61h]
  int v19; // [rsp+D0h] [rbp-60h]
  int v20; // [rsp+D4h] [rbp-5Ch]
  int v21; // [rsp+D8h] [rbp-58h]
  int v22; // [rsp+DCh] [rbp-54h]
  char s; // [rsp+E0h] [rbp-50h] BYREF
  char v24[23]; // [rsp+E1h] [rbp-4Fh] BYREF
  char v25[8]; // [rsp+F8h] [rbp-38h] BYREF
  char v26[8]; // [rsp+100h] [rbp-30h] BYREF
  char v27[8]; // [rsp+108h] [rbp-28h] BYREF
  char v28[4]; // [rsp+110h] [rbp-20h] BYREF
  int v29; // [rsp+114h] [rbp-1Ch]
  const char **v30; // [rsp+118h] [rbp-18h]
  int v31; // [rsp+120h] [rbp-10h]
  int v32; // [rsp+124h] [rbp-Ch]
  int v33; // [rsp+128h] [rbp-8h]
  bool v34; // [rsp+12Eh] [rbp-2h]

  v32 = 0;
  v31 = argc;
  v30 = argv;
  v29 = time(0LL);
  puts("func(?)=\"01abfc750a0c942167651c40d088531d\"?");
  s = getchar();
  fgets(v24, 21, stdin);
  v22 = time(0LL);
  v21 = v22 - v29;
  v33 = v22 - v29;
  if ( y >= 10 && ((((_BYTE)x - 1) * (_BYTE)x) & 1) != 0 )
    goto LABEL_13;
  while ( 1 )
  {
    v20 = strlen(&s);
    v34 = v20 != 21;
    if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
      break;
LABEL_13:
    v20 = strlen(&s);
  }
  while ( 1 )
  {
    v19 = 1;
    if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
      break;
    v19 = 1;
  }
  while ( v19 < 21 )
  {
    if ( y >= 10 && ((((_BYTE)x - 1) * (_BYTE)x) & 1) != 0 )
    {
      v18 = v21 ^ v24[v19 - 1];
      v17[0] = main::$_0::operator()(v27, (unsigned int)v18);
      v16[0] = main::$_1::operator()(v25, (unsigned int)*(&s + v21 + v19 - 1));
      v8 = main::$_1::operator() const(char)::{lambda(int)#1}::operator()(v16, 7LL);
      v18 = main::$_0::operator() const(char)::{lambda(char)#1}::operator()(v17, (unsigned int)v8);
      v15[0] = main::$_2::operator()(v28, (unsigned int)v18);
      v14[0] = main::$_2::operator()(v28, (unsigned int)*(&s + v21 + v19 - 1));
      v9 = main::$_2::operator() const(char)::{lambda(char)#1}::operator()(v14, 18LL);
      v13[0] = main::$_3::operator()(v26, (unsigned int)v9);
      v10 = main::$_3::operator() const(char)::{lambda(char)#1}::operator()(v13, 3LL);
      v12[0] = main::$_0::operator()(v27, (unsigned int)v10);
      v11 = main::$_0::operator() const(char)::{lambda(char)#1}::operator()(v12, 2LL);
      v18 = main::$_2::operator() const(char)::{lambda(char)#1}::operator()(v15, (unsigned int)v11);
    }
    do
    {
      v18 = v21 ^ v24[v19 - 1];
      v17[0] = main::$_0::operator()(v27, (unsigned int)v18);
      v16[0] = main::$_1::operator()(v25, (unsigned int)*(&s + v21 + v19 - 1));
      v3 = main::$_1::operator() const(char)::{lambda(int)#1}::operator()(v16, 7LL);
      v18 = main::$_0::operator() const(char)::{lambda(char)#1}::operator()(v17, (unsigned int)v3);
      v15[0] = main::$_2::operator()(v28, (unsigned int)v18);
      v14[0] = main::$_2::operator()(v28, (unsigned int)*(&s + v21 + v19 - 1));
      v4 = main::$_2::operator() const(char)::{lambda(char)#1}::operator()(v14, 18LL);
      v13[0] = main::$_3::operator()(v26, (unsigned int)v4);
      v5 = main::$_3::operator() const(char)::{lambda(char)#1}::operator()(v13, 3LL);
      v12[0] = main::$_0::operator()(v27, (unsigned int)v5);
      v6 = main::$_0::operator() const(char)::{lambda(char)#1}::operator()(v12, 2LL);
      v18 = main::$_2::operator() const(char)::{lambda(char)#1}::operator()(v15, (unsigned int)v6);
    }
    while ( enc[v19 - 1] != v18 );
    while ( y >= 10 && ((((_BYTE)x - 1) * (_BYTE)x) & 1) != 0 )
      ;
    ++v19;
  }
  if ( y >= 10 && ((((_BYTE)x - 1) * (_BYTE)x) & 1) != 0 )
    goto LABEL_16;
  while ( 1 )
  {
    puts("You win");
    if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
      break;
LABEL_16:
    puts("You win");
  }
  return 0;
}

分析之后, 可以写出等价的处理逻辑
((lastchar % 7) + nextchar) ^ (lastchar & 18 * 3 + 2) == enc[i]

每相邻两个字符进行加密操作,最后跟enc的字符相比较

这个字符串是#字符的md5值, 所以第一个字符是#, 这样就可以反推全部字符

py 复制代码
checklist = [
    243, 46, 24, 54, 225, 76, 34, 209, 249, 140, 
    64, 118, 244, 14, 0, 5, 163, 144, 14, 165
]

flag = '#'
for i in range(len(checklist)):
    lastc = ord(flag[-1])
    enci = checklist[i] 
    nextc = ((enci ^ (((lastc ^ 18) * 3) + 2)) & 0xFF) - (lastc % 7)
    flag += chr(nextc)

print(flag)

总结

至此BUU前100个逆向题打完, 后续的WP可能只出有价值的题目, 并不再按顺序打

相关推荐
风间琉璃""14 小时前
二进制与网络安全的关系
安全·机器学习·网络安全·逆向·二进制
A5rZ10 天前
CTF-RE 从0到N: windows反调试-获取Process Environment Block(PEB)信息来检测调试
逆向
诗雅颂20 天前
【js逆向学习】某多多anti_content逆向(补环境)
开发语言·javascript·webpack·逆向·拼多多·补环境·anti_content
CYRUS STUDIO24 天前
frida脚本,自动化寻址JNI方法
android·运维·自动化·逆向·移动安全·jni·frida
vortex51 个月前
安全见闻(9)——开阔眼界,不做井底之蛙
安全·网络安全·逆向·二进制·1024程序员节
九月镇灵将1 个月前
爬虫逆向学习(十一):实战分享反爬机制快速定位与破解
爬虫·python·学习·逆向·破解
sln_15501 个月前
DASCTF 2024金秋十月赛RE题wp
安全·逆向·ctf
CYRUS_STUDIO1 个月前
Android 下通过触发 SIGTRAP 信号实现反调试
android·linux·逆向
码农研究僧1 个月前
逆向 解密接口信息(附Demo)
javascript·爬虫·逆向·解密·decrypt
诗雅颂1 个月前
【js逆向学习】极志愿 javascript+python+rpc
javascript·python·学习·rpc·逆向