暑假第七周

[湖湘杯2018]HighwayHash64

HighwayHash是是伪随机的 函数(即键控散列函数)优化了速度 信息,由Jyrki Alakuijala、Bill Cox和Jan Wassenberg设计 谷歌研究
我看有大佬WP是通过导入HighwayHash-cffi包用python来爆破的
但我没安装成功,贴个博客地址
先运行看看回显
img
ida打开查看主函数有两处check
img

法一

两处check的retcode都是1,可以把第二处修改为2,爆破第一处check得到长度
第二处check地址为1400019D6
img
010edit修改
img
写个bat爆破长度

@echo off
:next
reverse.exe
if %ERRORLEVEL% EQU 2 echo !!!!!get_len!!!!! & goto next
if %ERRORLEVEL% EQU 1 echo again & goto next
if %ERRORLEVEL% EQU 0 echo ############   & goto next

可以得到flag长度为19,除去hxb2018{}中间数字有10位
img
对照github上HighwayHash源码分析sub_1400017A0函数
img
其中HighwayHashReset是修改过的
img
将下载下来的源码highwayhash.c里的HighwayHashReset修改
img
可以通过第一个check验证一下我们的修改是否正确
img

#include "highwayhash.h"
 
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
 
 
int main() {
  const uint64_t key[4]={0};
  uint8_t data[11] = {19};
  printf("%llx",HighwayHash64(data, 4, key));
  return 0;
}

结果正确,说明我们的修改是符合题目所给的,那我们就可以爆破了
img

exp

#include "highwayhash.h"
 
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
 
 
int main() {
  const uint64_t key[4]={0};
  uint8_t data[11]={0,0,0,0,0,0,0,0,0,0};
  for(uint8_t v1='9';v1>='0';v1--){
	for(uint8_t v2='9';v2>='0';v2--){
		for(uint8_t v3='9';v3>='0';v3--){
			for(uint8_t v4='9';v4>='0';v4--){
				for(uint8_t v5='9';v5>='0';v5--){
					for(uint8_t v6='9';v6>='0';v6--){
						for(uint8_t v7='9';v7>='0';v7--){
							for(uint8_t v8='9';v8>='0';v8--){
								for(uint8_t v9='9';v9>='0';v9--){
									for(uint8_t v10='9';v10>='0';v10--){
										data[0]=v1;
										data[1]=v2;
										data[2]=v3;
										data[3]=v4;
										data[4]=v5;
										data[5]=v6;
										data[6]=v7;
										data[7]=v8;
										data[8]=v9;
										data[9]=v10;
										if(HighwayHash64(data, 10, key) == 0xC886BDF39CB4ED72){
											puts((char *)data);
										}
										
  }    }    }    }    }    }    }    }    }  }
  return 0;
}

大概2-3分钟跑出结果
img

法二

调用函数有两种方法,一种是写一个dll注入到exe中进行调用,另一种则是将该exe直接改成dll,另外写一个exe来调用
考虑后者将exe修改成dll
可以用010editor修改pe的NT头

  • IMAGE_FILE_HEADER->Characteristics(文件属性)->2102h(DLL文件一般是2102h)
  • IMAGE_OPTIONAL_HEADER->AddressOfEntryPoint(程序执行入口RVA)->0000h
    img
    或者用DIE的PE菜单修改
    img
    img

exp

//#include "pch.h"
#include <iostream>
#include<windows.h>

typedef __int64(__fastcall *f)(__int64 buff, unsigned __int64 len);

f func;

void len()
{
    int i;
    unsigned long long  result;
    for (i = 0; i < 50; i++)
    {
        result = func((long long)&i, 4);
        if (result == 0xD31580A28DD8E6C4)
        {
            printf("Len is %d\n", i - 9);
            return;
        }
    }
    printf("Not found the lenn");
    return;
}

void hash()
{
    unsigned long long i;
    unsigned long long  result;
    char buff[20];
    for (i = 10000000000; i > 0; i--)
    {
        sprintf_s(buff, "%0.10llu", i);
        /*if (i % 100000 == 0)
        {
            printf("%0.10llu\n", i);
        }*/
        result = func((long long)buff, 10);
        if (result == 0xC886BDF39CB4ED72)
        {
            printf("flag is %lld\n", i);
            return;
        }
    }
}

int main()
{
    HINSTANCE hdll;

    hdll = LoadLibrary(TEXT("D:\\C++\\reverse.dll"));
    if (hdll == NULL)
    {
        printf("Load dll Error: %dn", GetLastError());
        return 0;
    }
    printf("Dll base is %llx\n", hdll);
    func = ((f)((char*)hdll + 0x17A0));
    len();
    hash();
}
/*
Dll base is 7ffb57d20000
Len is 10
flag is 9352641078
*/

大概跑5分钟的样子
img

flag

hxb2018{9352641078}

[XCTF2017]first

ida64打开,主函数分析如下

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  __useconds_t *v3; // rbp
  unsigned int v4; // eax
  int *v5; // rcx
  int v6; // edx
  unsigned int v7; // eax
  signed __int64 v8; // rcx
  __int64 v9; // rax
  char v10; // bl
  char v11; // dl
  void (**v12)(void *); // rbp
  char *v13; // r12
  pthread_t *v14; // r13
  void (*v15)(void *); // rdi
  unsigned __int64 i; // rcx
  char v17; // al
  int *v18; // rdx
  int v19; // esi
  unsigned int v20; // eax
  unsigned __int64 v21; // rdx
  char *v22; // rax
  char *v23; // rdx
  char v24; // di

  v3 = useconds;
  v4 = time(0LL);
  srand(v4);
  do
    *v3++ = 100 * (rand() % 1000);
  while ( v3 != (__useconds_t *)&unk_602208 );  // 随机生成某个数
  __isoc99_scanf("%63s", dword_602180);
  v5 = dword_602180;
  do
  {
    v6 = *v5++;
    v7 = ~v6 & (v6 - 16843009) & 0x80808080;
  }
  while ( !v7 );
  if ( (~v6 & (v6 - 16843009) & 0x8080) == 0 )
    v7 >>= 16;
  if ( (~v6 & (v6 - 16843009) & 0x8080) == 0 )
    v5 = (int *)((char *)v5 + 2);
  v8 = (char *)v5 - ((char *)dword_602180 + __CFADD__((_BYTE)v7, (_BYTE)v7) + 3);
  v9 = 0LL;
  v10 = 0;
  while ( v8 != v9 )
  {
    v11 = *((_BYTE *)dword_602180 + v9) + v9;   // 每个字符+索引
    ++v9;
    v10 ^= v11;                                 // 异或
  }
  v12 = (void (**)(void *))&newthread;
  v13 = 0LL;
  v14 = &newthread;
  do
  {
    if ( pthread_create(v14, 0LL, (void *(*)(void *))start_routine, v13) )// start_routine里有关键加密
    {
      perror("pthread_create");
      exit(-1);
    }
    ++v13;
    ++v14;
  }
  while ( v13 != (char *)6 );                   // 创建6个进程
  do
  {
    v15 = *v12++;
    pthread_join((pthread_t)v15, 0LL);
  }
  while ( &free != v12 );
  for ( i = 0LL; ; byte_60221F[i] = v10 ^ byte_6020DF[i] ^ v17 )// 和byte_6020DF以及前面用到的v10异或
                                                // byte_6020DF为
                                                // FE E9 F4 E2 F1 FA F4 E4 F0 E7 E4 E5 E3 F2 F5 EF E8 FF F6 F4 FD B4 A5 B2
  {
    v18 = dword_602180;
    do
    {
      v19 = *v18++;
      v20 = ~v19 & (v19 - 16843009) & 0x80808080;
    }
    while ( !v20 );
    if ( (~v19 & (v19 - 16843009) & 0x8080) == 0 )
      v20 >>= 16;
    if ( (~v19 & (v19 - 16843009) & 0x8080) == 0 )
      v18 = (int *)((char *)v18 + 2);
    v21 = (char *)v18 - ((char *)dword_602180 + __CFADD__((_BYTE)v20, (_BYTE)v20) + 3);
    if ( v21 <= i )
      break;
    v17 = *((_BYTE *)dword_602220 + i++);
  }
  if ( v21 )
  {
    if ( (unsigned __int8)(LOBYTE(dword_602220[0]) - 48) > 0x4Au )
    {
LABEL_32:
      puts("Badluck! There is no flag");
      return 0LL;
    }
    v22 = (char *)dword_602220 + 1;
    v23 = (char *)(v21 + 6300192);
    while ( v22 != v23 )
    {
      v24 = *v22++;
      if ( (unsigned __int8)(v24 - 48) > 0x4Au )
        goto LABEL_32;
    }
  }
  __printf_chk(1LL, "Here is the flag:%s\n", (const char *)dword_602220);// 正确输出dword_602220
  return 0LL;
}

跟进一下start_routine
img
sub_400E10里findcrypt插件有识别到md5的标志数组
img
那我们可以先爆破出来传入的数据得到juhuhfenlapsiuerhjifdunu

from hashlib import md5
from pwn import p64
 
ans = [0x0F59BB02BDBB4647,0x5CFCE8EC2128ACBE,0xEF0375CA659274AD,0x27422CC18FB38643,0xA72DECA745CC3EB0,0xE8341712FE5F3CBE]
ans = [p64(i) for i in ans]
print(ans)
for i in range(97,123):
    for j in range(97,123):
        for k in range(97,123):
            for l in range(97,123):
                enc = bytes([i,j,k,l])
                val = md5(enc).digest()[:8]
                if val in ans:
                    print(enc, val, ans.index(val))   
#[b'GF\xbb\xbd\x02\xbbY\x0f', b'\xbe\xac(!\xec\xe8\xfc\\', b'\xadt\x92e\xcau\x03\xef', b"C\x86\xb3\x8f\xc1,B'", b'\xb0>\xccE\xa7\xec-\xa7', b'\xbe<_\xfe\x12\x174\xe8']
# b'dunu' b'\xbe<_\xfe\x12\x174\xe8' 5
# b'hfen' b'\xbe\xac(!\xec\xe8\xfc\\' 1
# b'hjif' b'\xb0>\xccE\xa7\xec-\xa7' 4
# b'iuer' b"C\x86\xb3\x8f\xc1,B'" 3
# b'juhu' b'GF\xbb\xbd\x02\xbbY\x0f' 0
# b'laps' b'\xadt\x92e\xcau\x03\xef' 2     
#juhuhfenlapsiuerhjifdunu

真实的输入顺序不确定,6组字符组合一下,爆破一下顺序
如果用juhuhfenlapsiuerhjifdunu解出来是goodjobyougeytcnsflaj284
隐约能感觉到是最后1位和倒3位出了问题,交换一下
最后确定juhuhfenlapsdunuhjifiuer

input1 = 'juhuhfenlapsiuerhjifdunu'
check = [0xfe,0xe9,0xf4,0xe2,0xf1,0xfa,0xf4,0xe4,0xf0,0xe7,0xe4,0xe5,0xe3,0xf2,0xf5,0xef,0xe8,0xff,0xf6,0xf4,0xfd,0xb4,0xa5,0xb2]
len = 24
i = 0
v10 = 0
while(i != len):
	v11 = ord(input1[i]) + i
	v10 = v10 ^ v11
	i = i + 1

input2 = 'juhuhfenlapsdunuhjifiuer'
flag = ''
for i in range(24):
	temp = ord(input2[i]) ^ v10 ^ check[i]
	flag += chr(temp)
print(flag)
#goodjobyougetthisflag233

另外也可以在linux下运行,能爆出来结果
img

exp

from hashlib import md5
from pwn import p64
 
ans = [0x0F59BB02BDBB4647,0x5CFCE8EC2128ACBE,0xEF0375CA659274AD,0x27422CC18FB38643,0xA72DECA745CC3EB0,0xE8341712FE5F3CBE]
ans = [p64(i) for i in ans]
print(ans)
for i in range(97,123):
    for j in range(97,123):
        for k in range(97,123):
            for l in range(97,123):
                enc = bytes([i,j,k,l])
                val = md5(enc).digest()[:8]
                if val in ans:
                    print(enc, val, ans.index(val))   
#[b'GF\xbb\xbd\x02\xbbY\x0f', b'\xbe\xac(!\xec\xe8\xfc\\', b'\xadt\x92e\xcau\x03\xef', b"C\x86\xb3\x8f\xc1,B'", b'\xb0>\xccE\xa7\xec-\xa7', b'\xbe<_\xfe\x12\x174\xe8']
# b'dunu' b'\xbe<_\xfe\x12\x174\xe8' 5
# b'hfen' b'\xbe\xac(!\xec\xe8\xfc\\' 1
# b'hjif' b'\xb0>\xccE\xa7\xec-\xa7' 4
# b'iuer' b"C\x86\xb3\x8f\xc1,B'" 3
# b'juhu' b'GF\xbb\xbd\x02\xbbY\x0f' 0
# b'laps' b'\xadt\x92e\xcau\x03\xef' 2     
#juhuhfenlapsiuerhjifdunu
input1 = 'juhuhfenlapsiuerhjifdunu'
check = [0xfe,0xe9,0xf4,0xe2,0xf1,0xfa,0xf4,0xe4,0xf0,0xe7,0xe4,0xe5,0xe3,0xf2,0xf5,0xef,0xe8,0xff,0xf6,0xf4,0xfd,0xb4,0xa5,0xb2]
len = 24
i = 0
v10 = 0
while(i != len):
	v11 = ord(input1[i]) + i
	v10 = v10 ^ v11
	i = i + 1

input2 = 'juhuhfenlapsiuerhjifdunu'
flag = ''
for i in range(24):
	temp = ord(input2[i]) ^ v10 ^ check[i]
	flag += chr(temp)
print(flag)
#goodjobyougetthisflag233

flag

goodjobyougetthisflag233

[西湖论剑2019预选赛]Junk_instruction

MFC文件先打开看看,要求输入flag然后check
img
输入错误会弹出Error!提示
学习了一下MFC逆向,要使用XSPY
先检测一下check按钮,id=03e9
img
接着检测一下整个窗口
img
可以看到OnCommand: notifycode=0000 id=03e9,func= 0x00832420(Junk_Instruction.exe+ 0x002420 )
表示点击id=03e9即check的时候程序会跳转倒0x00832420地址的函数
ida打开定位到sub_402420
img
可以看到有个if判断,调用了sub_402600应该就是加密函数了,跟进一下
有点混乱应该是有花指令,返回去看汇编代码
发现有很多垃圾指令。就是先用一个call跳到下一段,没什么实际意义
全部nop
img
2AF0, 2CA0, 2e80这几个也有类似花指令函数同样的处理。
或者用idapython去花

from ida_bytes import get_bytes, patch_bytes
import re
addr = 0x402400
end = 0x403000
buf = get_bytes(addr, end-addr)
def handler1(s):
    s = s.group(0)
    print("".join(["%02x"%i for i in s]))
    s = b"\x90"*len(s)
    return s
p = b"\xe8\x00\x00\x00\x00.*?\xc3.*?\xc3"
buf = re.sub(p, handler1, buf, flags=re.I)
patch_bytes(addr, buf)
print("Done")

去花完sub_402600如下

char __cdecl sub_402600(int a1)
{
  int v1; // ecx
  const WCHAR *v2; // eax
  void *v3; // eax
  char v5; // [esp+8h] [ebp-4BCh]
  char v6[511]; // [esp+9h] [ebp-4BBh] BYREF
  int v7; // [esp+208h] [ebp-2BCh]
  char *v8; // [esp+20Ch] [ebp-2B8h]
  int v9; // [esp+210h] [ebp-2B4h]
  size_t Count; // [esp+214h] [ebp-2B0h]
  int v11; // [esp+218h] [ebp-2ACh]
  size_t v12; // [esp+21Ch] [ebp-2A8h]
  char *v13; // [esp+220h] [ebp-2A4h]
  char *v14; // [esp+224h] [ebp-2A0h]
  int v15; // [esp+228h] [ebp-29Ch]
  char v16[4]; // [esp+22Ch] [ebp-298h] BYREF
  char *Source; // [esp+230h] [ebp-294h]
  int v18; // [esp+234h] [ebp-290h]
  char v19; // [esp+238h] [ebp-28Ch]
  char v20; // [esp+239h] [ebp-28Bh]
  char v21; // [esp+23Ah] [ebp-28Ah]
  char v22; // [esp+23Bh] [ebp-289h]
  char v23; // [esp+23Ch] [ebp-288h]
  char v24; // [esp+23Dh] [ebp-287h]
  char v25; // [esp+23Eh] [ebp-286h]
  char v26; // [esp+23Fh] [ebp-285h]
  char v27; // [esp+240h] [ebp-284h]
  char v28; // [esp+241h] [ebp-283h]
  char v29; // [esp+242h] [ebp-282h]
  char v30; // [esp+243h] [ebp-281h]
  char v31; // [esp+244h] [ebp-280h]
  char v32; // [esp+245h] [ebp-27Fh]
  char v33; // [esp+246h] [ebp-27Eh]
  char v34; // [esp+247h] [ebp-27Dh]
  char v35; // [esp+248h] [ebp-27Ch]
  char v36; // [esp+249h] [ebp-27Bh]
  char v37; // [esp+24Ah] [ebp-27Ah]
  char v38; // [esp+24Bh] [ebp-279h]
  char v39; // [esp+24Ch] [ebp-278h]
  char v40; // [esp+24Dh] [ebp-277h]
  char v41; // [esp+24Eh] [ebp-276h]
  char v42; // [esp+24Fh] [ebp-275h]
  char v43; // [esp+250h] [ebp-274h]
  char v44; // [esp+251h] [ebp-273h]
  char v45; // [esp+252h] [ebp-272h]
  char v46; // [esp+253h] [ebp-271h]
  char v47; // [esp+254h] [ebp-270h]
  char v48; // [esp+255h] [ebp-26Fh]
  char v49; // [esp+256h] [ebp-26Eh]
  char v50; // [esp+257h] [ebp-26Dh]
  const char *v51; // [esp+258h] [ebp-26Ch]
  char *v52; // [esp+25Ch] [ebp-268h]
  int i; // [esp+260h] [ebp-264h]
  char *v54; // [esp+264h] [ebp-260h]
  char v55; // [esp+26Dh] [ebp-257h]
  char v56; // [esp+26Eh] [ebp-256h]
  char v57; // [esp+26Fh] [ebp-255h]
  char v58[28]; // [esp+270h] [ebp-254h] BYREF
  char v59; // [esp+28Ch] [ebp-238h] BYREF
  char v60[255]; // [esp+28Dh] [ebp-237h] BYREF
  char v61[256]; // [esp+38Ch] [ebp-138h] BYREF
  char Destination; // [esp+48Ch] [ebp-38h] BYREF
  char v63[39]; // [esp+48Dh] [ebp-37h] BYREF
  int v64; // [esp+4C0h] [ebp-4h]
  int savedregs; // [esp+4C4h] [ebp+0h] BYREF

  v18 = v1;
  v64 = 3;
  v19 = 0x5B;
  v20 = 0xD6;
  v21 = 0xD0;
  v22 = 0x26;
  v23 = 0xC8;
  v24 = 0xDD;
  v25 = 0x19;
  v26 = 0x7E;
  v27 = 0x6E;
  v28 = 0x3E;
  v29 = 0xCB;
  v30 = 0x16;
  v31 = 0x91;
  v32 = 0x7D;
  v33 = 0xFF;
  v34 = 0xAF;
  v35 = 0xDD;
  v36 = 0x76;
  v37 = 0x64;
  v38 = 0xB0;
  v39 = 0xF7;
  v40 = 0xE5;
  v41 = 0x89;
  v42 = 0x57;
  v43 = 0x82;
  v44 = 0x9F;
  v45 = 0xC;
  v46 = 0;
  v47 = 0x9E;
  v48 = 0xD0;
  v49 = 0x45;
  v50 = 0xFA;
  v2 = (const WCHAR *)sub_401570(&a1);
  v15 = sub_4030A0(v2);
  v11 = v15;
  v3 = (void *)sub_401570(v15);
  sub_403000(v3);
  sub_4012A0(v16);
  Source = (char *)unknown_libname_1(v58);
  v52 = Source;
  v14 = Source + 1;
  v52 += strlen(v52);
  v12 = ++v52 - (Source + 1);
  Count = v12;
  Destination = 0;
  memset(v63, 0, sizeof(v63));
  strncpy(&Destination, Source, v12);
  if ( sub_402AF0(&Destination) )
  {
    v55 = 0;
    v57 = 0;
LABEL_7:
    v56 = v57;
  }
  else
  {
    strcpy(v61, "qwertyuiop");
    memset(&v61[11], 0, 0xF5u);
    v59 = 0;
    memset(v60, 0, sizeof(v60));
    v5 = 0;
    memset(v6, 0, sizeof(v6));
    v51 = v61;
    v8 = &v61[1];
    v51 += strlen(v51);
    v7 = ++v51 - &v61[1];
    sub_402CA0(&v59, v61, v51 - &v61[1]);
    v54 = &Destination;
    v13 = v63;
    v54 += strlen(v54);
    v9 = ++v54 - v63;
    sub_402E80(v18, &v59, &Destination, v54 - v63);
    for ( i = 31; i >= 0; --i )
    {
      if ( *(&Destination + i) != *((char *)&savedregs + i + (_DWORD)&loc_4026B7 - 4204867) )
      {
        v57 = 0;
        goto LABEL_7;
      }
    }
    v56 = 1;
  }
  LOBYTE(v64) = 0;
  sub_403060(v58);
  v64 = -1;
  sub_4012A0(&a1);
  return v56;
}

sub_402CA0如下,一眼rc4
img
sub_402AF0如下,逆向数组操作
img

exp

from Crypto.Cipher import ARC4

key = b'qwertyuiop'
a = [
  0x5b, 0xd6, 0xd0, 0x26, 0xc8, 0xdd, 0x19, 0x7e, 0x6e, 0x3e,
  0xcb, 0x16, 0x91, 0x7d, 0xff, 0xaf, 0xdd, 0x76, 0x64, 0xb0, 
  0xf7, 0xe5, 0x89, 0x57, 0x82, 0x9f, 0xc, 0x0, 0x9e, 0xd0, 0x45, 0xfa]

enc = b''.join([bytes([i]) for i in a])
rc4 = ARC4.new(key)
decrypted_data = rc4.decrypt(enc)[::-1]
print(decrypted_data.decode('utf-8'))
#973387a11fa3f724d74802857d3e052f

img

flag

flag{973387a11fa3f724d74802857d3e052f}

posted @ 2023-08-15 00:35  Tree_24  阅读(71)  评论(0编辑  收藏  举报