[Dest0g3.reverse] simpleXOR,hi,tttea,EZMATH

最近一直作逆向,但还是不得要领,只作了4题

目录

simpleXOR

hi

tttea

EZMATH


simpleXOR

简单的是真简单,难的是真难,这题没有任何一个弯。

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4[72]; // [rsp+0h] [rbp-160h]
  char v5[52]; // [rsp+120h] [rbp-40h] BYREF
  int v6; // [rsp+154h] [rbp-Ch]
  unsigned int j; // [rsp+158h] [rbp-8h]
  int i; // [rsp+15Ch] [rbp-4h]

  v6 = 247;
  printf("input flag:");
  __isoc99_scanf("%s", v5);
  for ( i = 0; i <= 35; ++i )
  {
    v4[i + 36] = v5[i];
    v4[i] = v6 ^ (v4[i + 36] + i);
  }
  for ( j = 0; j <= 0x23; ++j )
  {
    if ( v4[j] != result_0[j] )
    {
      puts("Wrong!!!");
      return 0;
    }
    if ( j == 35 )
      puts("Success!!!");
  }
  return 0;
}

第一步作了个加序号再异或247,第二步就校验结果,所以解密也容易

data = open('520_simpleXOR', 'rb').read()[0x3060: 0x3060+36*4]
print(bytes([((data[i*4]) ^247) -i  for i in range(36)]))
#Dest0g3{0bcgf-AdMy892-KobPW-hB6LTqG}

hi

这个hi应该相当于misc里的签到,enc和x都给了,输入字符*23再作个加x最后得enc,两块复杂的运算相同直接减互得0不用管。

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int i; // [rsp+4h] [rbp-ACh]
  int v1; // [rsp+8h] [rbp-A8h]
  char enc[45]; // [rsp+10h] [rbp-A0h]
  char str[100]; // [rsp+40h] [rbp-70h] BYREF
  unsigned __int64 v8; // [rsp+A8h] [rbp-8h]

  v8 = __readfsqword(0x28u);
  memset(str, 0, sizeof(str));
  *(_QWORD *)enc = 0x9F8E7A1CC6486497LL;
  *(_QWORD *)&enc[8] = 0x69EEF382E760BD46LL;
  *(_QWORD *)&enc[16] = 0xB9C017E2E30EF749LL;
  *(_QWORD *)&enc[24] = 0x98410148A430392CLL;
  *(_QWORD *)&enc[32] = 0xE80E7411E5B5A939LL;
  *(_DWORD *)&enc[40] = 0xA58BFDAC;
  enc[44] = 'm';
  fwrite("input: ", 1uLL, 7uLL, stdout);
  fgets(str, 46, stdin);
  if ( strlen(str) != 45 )
    exit(0);
  for ( i = 0; i <= 44; ++i )
  {
    v1 = 23 * str[i];
    if ( ((unsigned int)((v1 + x[i]) >> 31) >> 24) + (_BYTE)v1 + x[i] - ((unsigned int)((v1 + x[i]) >> 31) >> 24) != enc[i] )
      exit(0);
  }
  puts("good!");
  return 0;
}

解密直接用enc-x再乘23对256的逆:167

from pwn import *
x = open('hi', 'rb').read()[0x3020: 0x3020+45]
print(x)
enc = p64(0x9F8E7A1CC6486497)+p64(0x69EEF382E760BD46)+p64(0xB9C017E2E30EF749)+p64(0x98410148A430392C)+p64(0xE80E7411E5B5A939)+p32(0xA58BFDAC)+b'm'
print(enc)

print(bytes([(((enc[i]-x[i])&0xff )*167) & 0xff for i in range(len(enc))]))
#Dest0g3{f982cd79-d7a3-0874-aa0b-a5b37e4445c8}

tttea

看名字是tea加密,打开还真是tea加密,只是少了个密钥这块。

int __cdecl main_0(int argc, const char **argv, const char **envp)
{
  size_t v4; // eax
  char v5; // [esp+0h] [ebp-154h]
  char v6; // [esp+0h] [ebp-154h]
  int i; // [esp+D0h] [ebp-84h]
  int v8; // [esp+DCh] [ebp-78h]
  char Str[104]; // [esp+E8h] [ebp-6Ch] BYREF

  __CheckForDebuggerJustMyCode(&byte_40C015);
  memset(Str, 0, 0x64u);
  sub_401082("Please input your flag: ", v5);
  sub_401023("%s", (char)Str);
  if ( strlen(Str) == 44 )
  {
    v4 = strlen(Str);
    tea((int)Str, v4 >> 2, dword_40A018);
    v8 = 0;
    for ( i = 0; i < 44; ++i )
    {
      if ( Str[i] == byte_40A01C[i] )
        ++v8;
    }
    if ( v8 == 44 )
      sub_401082("success!\n", v6);
    else
      sub_401082("wrong!\n", v6);
    return 0;
  }
  else
  {
    sub_401082("wrong!\n", v6);
    return 0;
  }
}
int __cdecl sub_401660(_DWORD *flag, int len4, int delta)
{
  int v3; // eax
  int v4; // edx
  int v5; // edx
  int result; // eax
  int v7; // [esp+E0h] [ebp-44h]
  int v8; // [esp+ECh] [ebp-38h]
  unsigned int i; // [esp+F8h] [ebp-2Ch]
  unsigned int v10; // [esp+104h] [ebp-20h]
  unsigned int v11; // [esp+110h] [ebp-14h]

  __CheckForDebuggerJustMyCode(&byte_40C015);
  v8 = 52 / len4 + 6;
  v10 = 0;
  v11 = flag[len4 - 1];
  do
  {
    v10 += delta;
    v7 = (v10 >> 2) & 3;
    for ( i = 0; i < len4 - 1; ++i )
    {
      v3 = ((v11 ^ *((char *)&delta + (v7 ^ i & 3))) + (flag[i + 1] ^ v10)) ^ (((16 * v11) ^ (flag[i + 1] >> 3))
                                                                             + ((4 * flag[i + 1]) ^ (v11 >> 6)));
      v4 = flag[i];
      flag[i] = v3 + v4;
      v11 = v3 + v4;
    }
    v5 = (((v11 ^ *((char *)&delta + (v7 ^ i & 3))) + (*flag ^ v10)) ^ (((16 * v11) ^ (*flag >> 3))
                                                                      + ((4 * *flag) ^ (v11 >> 6))))
       + flag[len4 - 1];
    flag[len4 - 1] = v5;
    v11 = v5;
    result = --v8;
  }
  while ( v8 );
  return result;
}

程序也容易写,最近作了好几道tea的题,思路一样能看懂其实就好写了

from libnum import s2n,n2s
c = bytes.fromhex('0323222F3688FD4321E85B65311E3BA64BB8DC888019846F97722126AD64EEBB88044D062F26E56B814BF573')

delta = 9E3779B9
print(hex(delta)) #0x74746561
#del_arr = [0x61, 0x65, 0x74, 74]
del_arr = n2s(delta)[::-1]
p = []
for i in del_arr:
    if i&0x80 != 0:
        p.append(i+0xffffff)
    else:
        p.append(i)
del_arr = p 
print(','.join([hex(i) for i in del_arr]))

tab = [delta*(i+1)& 0xffffffff for i in range(10)]
print(",".join([hex(i) for i in tab]))

def decrypt(c):
    flag = [s2n(c[i: i+4][::-1]) for i in range(0, len(c), 4)]
    for i in range(9,-1,-1):  #10轮加密
        v10 = tab[i]
        v7 = (v10>>2)&3
        #print(hex(v10))
        for j in range(10,-1,-1): #11组 * 4
            i_big = (j+1)%11
            i_small = (j-1)%11
            v11 = flag[i_small]
            v12 = flag[i_big]
            v3 = ((v11 ^ del_arr[v7 ^ j & 3])+(v12 ^ v10) ) ^ ((((v11<<4) &0xffffffff)^ (v12 >> 3))+(((v12<<2)&0xffffffff) ^ (v11 >> 6)))
            flag[j] = (flag[j] - v3)&0xffffffff 
        print(",".join([hex(i)[2:] for i in flag]))
    m = b''
    for i in flag:
        m +=n2s(i)[::-1] 
    print(m)

def encrypt(c):
    flag = [s2n(c[i: i+4][::-1]) for i in range(0, len(c), 4)]
    for i in range(10):  #10轮加密
        v10 = tab[i]
        v7 = (v10>>2)&3
        #print(hex(v10))
        for j in range(11): #11组 * 4
            i_big = (j+1)%11
            i_small = (j-1)%11
            v11 = flag[i_small]
            v12 = flag[i_big]
            v3 = ((v11 ^ del_arr[v7 ^ j & 3])+(v12 ^ v10) ) ^ ((((v11<<4) &0xffffffff)^ (v12 >> 3))+(((v12<<2)&0xffffffff) ^ (v11 >> 6)))
            flag[j] = (flag[j] + v3)&0xffffffff 
        print(",".join([hex(i)[2:] for i in flag]))
    m = b''
    for i in flag:
        m +=n2s(i)[::-1]   
    print(m)
    return m 

#c = encrypt(b'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGH')
decrypt(c)

解完发现不对,怎么也不对,用od跟进去结果是跟我的加密解密算法结果相同,再看程序里边有几处反调的地方结处理掉了,还似乎看到一个SEH这个反调就是发现调试时干点啥,一般是断掉,但这题明显在调试的时候没什么影响运行。猜是偷偷把东西改了。

然后在函数里找,找到两个函数,第1个把delta值改了,第2个还作了个异或。它在发现调试时就不运行这两个函数,异至跟进去和不跟进去不一样。

NTSTATUS __stdcall TlsCallback_0_0(int a1, int a2, int a3)
{
  HANDLE CurrentProcess; // eax
  NTSTATUS result; // eax
  NTSTATUS (__stdcall *NtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG); // [esp+D0h] [ebp-14h]
  HMODULE hModule; // [esp+DCh] [ebp-8h]

  __CheckForDebuggerJustMyCode(byte_40C015);
  hModule = LoadLibraryA("Ntdll.dll");
  NtQueryInformationProcess = (NTSTATUS (__stdcall *)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG))GetProcAddress(hModule, "NtQueryInformationProcess");
  CurrentProcess = GetCurrentProcess();
  result = NtQueryInformationProcess(CurrentProcess, ProcessDebugPort, &dword_40A1FC, 4, 0);
  if ( !dword_40A1FC )
  {
    result = 1;
    *(&dword_40A000 + 6) = 0x66403319;
  }
  return result;
}
char *__stdcall TlsCallback_1_0(int a1, int a2, int a3)
{
  char *result; // eax
  signed __int8 BeingDebugged; // [esp+EBh] [ebp-5h]

  BeingDebugged = NtCurrentPeb()->BeingDebugged;
  result = (char *)BeingDebugged;
  if ( !BeingDebugged )
  {
    result = (char *)&unk_40A014 + 4;
    *((_DWORD *)&unk_40A014 + 1) ^= 0x12345678u;
  }
  return result;
}

把delta改掉后就出结果了

delta = 0x66403319 ^ 0x12345678 # 9E3779B9 TlsCallback_0_0  TlsCallback_1_0
#Dest0g3{73dd38c2-9d45-4f7a-9bd0-90a1e9907c1}

EZMATH

打开包发现json文件这个应该是用.net作的,用dnSpy打开,找到加密函数

namespace EzMath
{
	// Token: 0x02000003 RID: 3
	public static class Checker
	{
		// Token: 0x06000005 RID: 5 RVA: 0x00002110 File Offset: 0x00000310
		public static byte[] Encrypt1(byte[] a)
		{
			List<byte> list = new List<byte>();
			for (int i = 0; i < 8; i++)
			{
				uint num = (uint)((ulong)utils.Unpack32(RuntimeHelpers.GetSubArray<byte>(a, new Range(4 * i, 4 * (i + 1)))) * 83987UL % (ulong)-232573883);
				list.AddRange(BitConverter.GetBytes(num));
			}
			return list.ToArray();
		}

		// Token: 0x06000006 RID: 6 RVA: 0x00002174 File Offset: 0x00000374
		public static byte[] Encrypt2(byte[] a)
		{
			List<byte> list = new List<byte>();
			for (int i = 0; i < 4; i++)
			{
				ulong num = utils.Unpack64(RuntimeHelpers.GetSubArray<byte>(a, new Range(8 * i, 8 * (i + 1))));
				ulong num2 = num ^ num >> 25;
				list.AddRange(BitConverter.GetBytes(num2));
			}
			return list.ToArray();
		}
	}
}
using System;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using EzMath;

// Token: 0x02000002 RID: 2
[CompilerGenerated]
internal class Program
{
	// Token: 0x06000001 RID: 1 RVA: 0x00002050 File Offset: 0x00000250
	private static void <Main>$(string[] args)
	{
		Console.Write("Input your flag:");
		string text = Console.ReadLine();
		if (!Program.<<Main>$>g__FormatChecker|0_0(text))
		{
			Program.<<Main>$>g__err|0_1();
		}
		string text2 = text.Replace("-", string.Empty);
		byte[] second = Checker.Encrypt2(Checker.Encrypt1(Encoding.ASCII.GetBytes(text2)));
		if (new byte[]
		{
			218,49,230,35,65,168,134,53,233,62,212,
			208,127,224,63,164,36,88,65,138,118,255,
			107,22,16,239,61,58,130,101,227,109
		}.SequenceEqual(second))
		{
			Console.WriteLine("right!");
			Console.WriteLine("Your flag is Dest0g3{" + text + "}");
			return;
		}
		Program.<<Main>$>g__err|0_1();
	}

	// Token: 0x06000003 RID: 3 RVA: 0x000020E8 File Offset: 0x000002E8
	[CompilerGenerated]
	internal static bool <<Main>$>g__FormatChecker|0_0(string input)
	{
		Guid guid;
		return Guid.TryParse(input, out guid);
	}

	// Token: 0x06000004 RID: 4 RVA: 0x000020FD File Offset: 0x000002FD
	[CompilerGenerated]
	internal static void <<Main>$>g__err|0_1()
	{
		Console.WriteLine("err!");
		Environment.Exit(1);
	}
}

对输入内容作了两次加密encrypt1,encrypt2第1次是乘模运算,用乘法的逆再作个乘模运算就能回来,第2次是移位再异或运算,把暴露部分依次向后异或得到原值 。这两个都很容易。

from libnum import s2n,n2s
from gmpy2 import invert
c = [218,49,230,35,65,168,134,53,233,62,212,208,127,224,63,164,36,88,65,138,118,255,107,22,16,239,61,58,130,101,227,109]
#Encrypt1    m * 83987 % -232573883
p = -232573883 & 0xffffffff
d = int(invert(83987, p ))
def decrypt1(s):
    t = b''
    for i in range(8):
        k = u32(s[i*4: i*4+4])
        k = k * d % p 
        t += p32(k)
    return t 
#Encrypt2    m ^ (m>>25)    a:25 b:25 c:14
def decrypt2(s):
    t = b''
    for i in range(4):
        k = u64(s[i*8: i*8+8])
        ka = (k>>(25+14))&0x1ffffff
        kb = (k>>14)&0x1ffffff
        kc = k & 0x3fff
        a = ka
        b = a^kb
        c = (b>>11)^kc
        k = (a<<(25+14)) | (b<<14) | c 
        t += p64(k)
    return t 

c = bytes(c)
c = decrypt2(c)
c = decrypt1(c)
print(c)
#28956fc4c54045a8808d42a5fab4b5f8
#Dest0g3{28956fc4-c540-45a8-808d-42a5fab4b5f8}   

这题结果只是个芯,还要自己加壳改为UUID格式(输入时把-滤掉了),本来已经出结果了,居然一直没看到,还在找程序哪有问题。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值