HFCTF2022RE部分WP

fpbe

这题通过题目了解到了这是一个用了BPF的程序
通过查看https://github.com/libbpf/libbpf/blob/master/src/libbpf.h
可以知道对程序进行了hook

/**
 * @brief **bpf_program__attach_uprobe()** attaches a BPF program
 * to the userspace function which is found by binary path and
 * offset. You can optionally specify a particular proccess to attach
 * to. You can also optionally attach the program to the function
 * exit instead of entry.
 *
 * @param prog BPF program to attach
 * @param retprobe Attach to function exit
 * @param pid Process ID to attach the uprobe to, 0 for self (own process),
 * -1 for all processes
 * @param binary_path Path to binary that contains the function symbol
 * @param func_offset Offset within the binary of the function symbol
 * @return Reference to the newly created BPF link; or NULL is returned on error,
 * error code is stored in errno
 */
LIBBPF_API struct bpf_link *
bpf_program__attach_uprobe(const struct bpf_program *prog, bool retprobe,
			   pid_t pid, const char *binary_path,
			   size_t func_offset);

//源程序代码
skel->links.uprobe = bpf_program__attach_uprobe(
                               skel->progs.uprobe,  //附加的BPF程序
                               0,
                               0,
                               "/proc/self/exe",
                               (size_t)uprobed_function - base_addr); 

查找skel->progs.uprobe的内容

int __cdecl fpbe_bpf__create_skeleton(fpbe_bpf *obj)
{
  int result; // eax
  bpf_object_skeleton *s; // [rsp+18h] [rbp-8h]

  s = (bpf_object_skeleton *)calloc(1LL, 72LL);
  if ( !s )
    return -1;
  obj->skeleton = s;
  s->sz = 72LL;
  s->name = "fpbe_bpf";
  s->obj = &obj->obj;
  s->prog_cnt = 1;
  s->prog_skel_sz = 24;
  s->progs = (bpf_prog_skeleton *)calloc(s->prog_cnt, s->prog_skel_sz);
  if ( s->progs )
  {
    s->progs->name = "uprobe";
    s->progs->prog = &obj->progs.uprobe;
    s->progs->link = &obj->links.uprobe;
    s->data_sz = 1648LL;                        // 附加程序字节码的大小
    s->data = &loc_4F4018;                      // 附加程序的字节码
    result = 0;
  }
  else
  {
    bpf_object__destroy_skeleton(s);
    result = -1;
  }
  return result;
}

运行脚本dump出字节码

static main()
{
    auto i,fp;
    fp = fopen("C://Users//12196//Desktop//dump","wb"); //dump数据存储的路径
    auto start = 0x4F4018; //这里填入要dump的代码的起始地址
    auto size = 0x670; //这里填入要dump的代码的大小
    for(i=start;i<start+size;i++)
    {
        fputc(Byte(i),fp);
    }
}

反汇编字节码

dump:	file format ELF64-BPF


Disassembly of section uprobe/func:

0000000000000000 uprobe:
       0:	79 12 68 00 00 00 00 00	r2 = *(u64 *)(r1 + 104)
       1:	67 02 00 00 20 00 00 00	r2 <<= 32
       2:	77 02 00 00 20 00 00 00	r2 >>= 32
       3:	79 13 70 00 00 00 00 00	r3 = *(u64 *)(r1 + 112)
       4:	67 03 00 00 20 00 00 00	r3 <<= 32
       5:	77 03 00 00 20 00 00 00	r3 >>= 32
       6:	bf 34 00 00 00 00 00 00	r4 = r3
       7:	27 04 00 00 c0 6d 00 00	r4 *= 28096
       8:	bf 25 00 00 00 00 00 00	r5 = r2
       9:	27 05 00 00 88 fb 00 00	r5 *= 64392
      10:	0f 45 00 00 00 00 00 00	r5 += r4
      11:	79 14 60 00 00 00 00 00	r4 = *(u64 *)(r1 + 96)
      12:	67 04 00 00 20 00 00 00	r4 <<= 32
      13:	77 04 00 00 20 00 00 00	r4 >>= 32
      14:	bf 40 00 00 00 00 00 00	r0 = r4
      15:	27 00 00 00 fb 71 00 00	r0 *= 29179
      16:	0f 05 00 00 00 00 00 00	r5 += r0
      17:	79 11 58 00 00 00 00 00	r1 = *(u64 *)(r1 + 88)
      18:	b7 00 00 00 00 00 00 00	r0 = 0
      19:	73 0a f8 ff 00 00 00 00	*(u8 *)(r10 - 8) = r0
      20:	7b 0a f0 ff 00 00 00 00	*(u64 *)(r10 - 16) = r0
      21:	7b 0a e8 ff 00 00 00 00	*(u64 *)(r10 - 24) = r0
      22:	67 01 00 00 20 00 00 00	r1 <<= 32
      23:	77 01 00 00 20 00 00 00	r1 >>= 32
      24:	bf 10 00 00 00 00 00 00	r0 = r1
      25:	27 00 00 00 8e cc 00 00	r0 *= 52366
      26:	0f 05 00 00 00 00 00 00	r5 += r0
      27:	b7 06 00 00 01 00 00 00	r6 = 1
      28:	18 00 00 00 95 59 73 a1 00 00 00 00 18 be 00 00	r0 = 209012997183893 ll
      30:	5d 05 42 00 00 00 00 00	if r5 != r0 goto +66 <LBB0_5>
      31:	bf 35 00 00 00 00 00 00	r5 = r3
      32:	27 05 00 00 bf f1 00 00	r5 *= 61887
      33:	bf 20 00 00 00 00 00 00	r0 = r2
      34:	27 00 00 00 e5 6a 00 00	r0 *= 27365
      35:	0f 50 00 00 00 00 00 00	r0 += r5
      36:	bf 45 00 00 00 00 00 00	r5 = r4
      37:	27 05 00 00 d3 ad 00 00	r5 *= 44499
      38:	0f 50 00 00 00 00 00 00	r0 += r5
      39:	bf 15 00 00 00 00 00 00	r5 = r1
      40:	27 05 00 00 84 92 00 00	r5 *= 37508
      41:	0f 50 00 00 00 00 00 00	r0 += r5
      42:	18 05 00 00 40 03 54 e5 00 00 00 00 56 a5 00 00	r5 = 181792633258816 ll
      44:	5d 50 34 00 00 00 00 00	if r0 != r5 goto +52 <LBB0_5>
      45:	bf 35 00 00 00 00 00 00	r5 = r3
      46:	27 05 00 00 85 dd 00 00	r5 *= 56709
      47:	bf 20 00 00 00 00 00 00	r0 = r2
      48:	27 00 00 00 28 80 00 00	r0 *= 32808
      49:	0f 50 00 00 00 00 00 00	r0 += r5
      50:	bf 45 00 00 00 00 00 00	r5 = r4
      51:	27 05 00 00 2d 65 00 00	r5 *= 25901
      52:	0f 50 00 00 00 00 00 00	r0 += r5
      53:	bf 15 00 00 00 00 00 00	r5 = r1
      54:	27 05 00 00 12 e7 00 00	r5 *= 59154
      55:	0f 50 00 00 00 00 00 00	r0 += r5
      56:	18 05 00 00 a3 4d 48 74 00 00 00 00 f3 a6 00 00	r5 = 183564558159267 ll
      58:	5d 50 26 00 00 00 00 00	if r0 != r5 goto +38 <LBB0_5>
      59:	bf 35 00 00 00 00 00 00	r5 = r3
      60:	27 05 00 00 2c 82 00 00	r5 *= 33324
      61:	bf 20 00 00 00 00 00 00	r0 = r2
      62:	27 00 00 00 43 ca 00 00	r0 *= 51779
      63:	0f 50 00 00 00 00 00 00	r0 += r5
      64:	bf 45 00 00 00 00 00 00	r5 = r4
      65:	27 05 00 00 8e 7c 00 00	r5 *= 31886
      66:	0f 50 00 00 00 00 00 00	r0 += r5
      67:	bf 15 00 00 00 00 00 00	r5 = r1
      68:	27 05 00 00 3a f2 00 00	r5 *= 62010
      69:	0f 50 00 00 00 00 00 00	r0 += r5
      70:	18 05 00 00 77 72 5a 48 00 00 00 00 9c b9 00 00	r5 = 204080879923831 ll
      72:	5d 50 18 00 00 00 00 00	if r0 != r5 goto +24 <LBB0_5>
      73:	63 1a f4 ff 00 00 00 00	*(u32 *)(r10 - 12) = r1
      74:	63 4a f0 ff 00 00 00 00	*(u32 *)(r10 - 16) = r4
      75:	63 2a ec ff 00 00 00 00	*(u32 *)(r10 - 20) = r2
      76:	63 3a e8 ff 00 00 00 00	*(u32 *)(r10 - 24) = r3
      77:	18 01 00 00 43 54 46 7b 00 00 00 00 25 73 7d 0a	r1 = 755886917287302211 ll
      79:	7b 1a d8 ff 00 00 00 00	*(u64 *)(r10 - 40) = r1
      80:	18 01 00 00 46 4c 41 47 00 00 00 00 3a 20 48 46	r1 = 5064333215653776454 ll
      82:	7b 1a d0 ff 00 00 00 00	*(u64 *)(r10 - 48) = r1
      83:	18 01 00 00 45 21 20 59 00 00 00 00 4f 55 52 20	r1 = 2329017756590022981 ll
      85:	7b 1a c8 ff 00 00 00 00	*(u64 *)(r10 - 56) = r1
      86:	18 01 00 00 57 45 4c 4c 00 00 00 00 20 44 4f 4e	r1 = 5642803763628229975 ll
      88:	7b 1a c0 ff 00 00 00 00	*(u64 *)(r10 - 64) = r1
      89:	b7 06 00 00 00 00 00 00	r6 = 0
      90:	73 6a e0 ff 00 00 00 00	*(u8 *)(r10 - 32) = r6
      91:	bf a1 00 00 00 00 00 00	r1 = r10
      92:	07 01 00 00 c0 ff ff ff	r1 += -64
      93:	bf a3 00 00 00 00 00 00	r3 = r10
      94:	07 03 00 00 e8 ff ff ff	r3 += -24
      95:	b7 02 00 00 21 00 00 00	r2 = 33
      96:	85 00 00 00 06 00 00 00	call 6

0000000000000308 LBB0_5:
      97:	bf 60 00 00 00 00 00 00	r0 = r6
      98:	95 00 00 00 00 00 00 00	exit

r1 * 28096 + r2 * 64392 + r3 * 29179 + r4 * 52366 = 209012997183893

r1 * 61887+ r2 * 27365+ r3 * 44499+ r4 * 37508= 181792633258816

r1 * 56709+ r2 * 32808+ r3 * 25901+ r4 * 59154= 183564558159267

r1 * 33324+ r2 * 51779+ r3 * 31886+ r4 * 62010= 204080879923831

使用z3求解

import struct
from typing import KeysView
from z3 import *
from Crypto.Util.number import *
solver = Solver()
r1,r2,r3,r4 = Ints("r1 r2 r3 r4")

solver.add(r1 * 28096 + r2 * 64392 + r3 * 29179 + r4 * 52366 == 209012997183893)
solver.add(r1 * 61887 + r2 * 27365 + r3 * 44499 + r4 * 37508 == 181792633258816)
solver.add(r1 * 56709 + r2 * 32808 + r3 * 25901 + r4 * 59154 == 183564558159267)
solver.add(r1 * 33324 + r2 * 51779 + r3 * 31886 + r4 * 62010 == 204080879923831)

print(solver.check())
print(solver.model())
keys = solver.model()

flag = ''

for i in [r1,r2,r3,r4]:
    print(hex(keys[i].as_long()))
    flag += struct.pack('<I',keys[i].as_long()).decode('utf-8')

print(flag)
#0vR3sAlbs8pD2h53

the_shellcode

使用ScyllaHide+Magicmida脱去themida壳并dump下文件

文件主要逻辑是先对输入的shellcode进行base64解密,再rol循环左移3位,之后再用魔改xxtea加密,最后再用输入的shellcode检验flag

在这里插入图片描述

xxtea密文

unsigned char ida_chars[] =
{
  0xA1, 0x89, 0x6B, 0x4B, 0x53, 0x54, 0xC1, 0x74, 0x6E, 0xA0, 
  0x92, 0x40, 0x07, 0x0C, 0x9B, 0x42, 0x84, 0x1E, 0x28, 0x40, 
  0xC9, 0x44, 0x5B, 0x8B, 0x7B, 0xB3, 0xFE, 0x66, 0x03, 0xA6, 
  0x77, 0x3C, 0x2D, 0x89, 0xC5, 0x79, 0x97, 0xDA, 0x7A, 0x0D, 
  0x56, 0xAA, 0x51, 0x1D, 0x03, 0xD7, 0xD4, 0x02, 0xBA, 0x26, 
  0xA5, 0x4F, 0x4A, 0xD6, 0xFA, 0x32, 0x91, 0x60, 0x0F, 0x0C, 
  0x93, 0x75, 0x2B, 0x56, 0x67, 0xDD, 0x9A, 0xDB, 0x63, 0x55, 
  0x16, 0x76, 0x15, 0x93, 0xF7, 0xA5, 0x1D, 0x99, 0xEB, 0x3A, 
  0xD4, 0x21, 0xB7, 0x1A, 0x2C, 0x9D, 0xCD, 0xAA, 0x27, 0x2B, 
  0x5C, 0x82, 0x1A, 0x76, 0xA7, 0x76, 0x18, 0x5F, 0x00, 0xB4, 
  0x63, 0x37, 0x7F, 0x11, 0x40, 0xC5, 0x2C, 0x51, 0x6F, 0xA1, 
  0x94, 0xC5, 0x8C, 0x4F, 0xE2, 0xD0, 0xE9, 0xE2, 0xA3, 0x9C, 
  0xD5, 0xC2, 0x9C, 0x0A, 0x1D, 0xE6, 0x29, 0x46, 0xE3, 0x29, 
  0x71, 0x63, 0xD7, 0x8A, 0x4E, 0xCA, 0x71, 0xAF, 0xDF, 0xF5, 
  0xAB, 0x68, 0x4E, 0x47, 0x3A, 0xBC, 0x2F, 0x54, 0x17, 0x16, 
  0x74, 0xD6, 0xE5, 0xBB, 0x0D, 0xAD, 0xE3, 0xBB, 0xF7, 0x62, 
  0x07, 0x8C, 0xD6, 0xC8, 0x0E, 0x95, 0x0E, 0x88, 0xBA, 0x25, 
  0x0F, 0xF8, 0x4C, 0x26, 0x7A, 0x76, 0x14, 0xE0, 0x7C, 0x9A, 
  0xEE, 0xC9, 0x8B, 0x5C, 0xD4, 0xF7, 0x9E, 0x5D, 0xDE, 0xAC, 
  0x99, 0xB9, 0x13, 0x8E, 0xEC, 0xB2, 0x2D, 0x23, 0x68, 0xEE, 
  0xCE, 0x5F, 0x7C, 0x92, 0x5D, 0xA8, 0xE3, 0xC9, 0x6B, 0xB5, 
  0x74, 0xAC, 0x12, 0xE7, 0xB6, 0x42, 0xDA, 0x98, 0x28, 0xCD, 
  0x58, 0x1C, 0xF1, 0xFC, 0xEE, 0x75, 0x70, 0xF5, 0x78, 0xE6, 
  0x76, 0x50, 0x35, 0x6A, 0xD6, 0xD4, 0xB9, 0x5A, 0x10, 0x95, 
  0x03, 0x44, 0xB0, 0x1B, 0x59, 0xB9, 0x40, 0xB2, 0x1A, 0x26, 
  0x4E, 0x7B, 0xD8, 0x29, 0xD1, 0x23, 0xCD, 0x52, 0xE7, 0xF5, 
  0x70, 0x8F, 0xA7, 0x4E
};

解密代码
参考https://bbs.pediy.com/thread-266933.htm#msg_header_h1_3

#include <stdio.h>
#include <stdint.h>
#define DELTA 0x61C88647            //固定的一个常量
#define MX (((z>>6^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z))) //魔改
//#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))   //固定的运算
void btea(uint32_t *v, int n, uint32_t const key[4])   //v是要加密的两个元素的数组
{                                                      //n为数组的长度
    uint32_t y, z, sum;                                //无符号整型
    unsigned p, rounds, e;
    if (n > 1)            /* Coding Part */
    {
        rounds = 6 + 52/n;               //固定的得出轮数
        sum = 0;
        z = v[n-1];
        do
        {
            sum += DELTA;                //每次进行叠加
            e = (sum >> 2) & 3;          //固定运算
            for (p=0; p<n-1; p++)
            {
                y = v[p+1];
                v[p] += MX;
                z = v[p];
            }
            y = v[0];
            z = v[n-1] += MX;
        }
        while (--rounds);
    }
    else if (n < -1)      /* Decoding Part */
    {
        n = -n;
        rounds = 6 + 52/n;
        sum = 0 - rounds*DELTA;
        y = v[0];
        do
        {
            e = (sum >> 2) & 3;
            for (p=n-1; p>0; p--)
            {
                z = v[p-1];
                y = v[p] -= MX;
            }
            z = v[n-1];
            y = v[0] -= MX;
            sum += DELTA;
        }
        while (--rounds);
    }
}
unsigned char ida_chars[] =
        {
                0xA1, 0x89, 0x6B, 0x4B, 0x53, 0x54, 0xC1, 0x74, 0x6E, 0xA0,
                0x92, 0x40, 0x07, 0x0C, 0x9B, 0x42, 0x84, 0x1E, 0x28, 0x40,
                0xC9, 0x44, 0x5B, 0x8B, 0x7B, 0xB3, 0xFE, 0x66, 0x03, 0xA6,
                0x77, 0x3C, 0x2D, 0x89, 0xC5, 0x79, 0x97, 0xDA, 0x7A, 0x0D,
                0x56, 0xAA, 0x51, 0x1D, 0x03, 0xD7, 0xD4, 0x02, 0xBA, 0x26,
                0xA5, 0x4F, 0x4A, 0xD6, 0xFA, 0x32, 0x91, 0x60, 0x0F, 0x0C,
                0x93, 0x75, 0x2B, 0x56, 0x67, 0xDD, 0x9A, 0xDB, 0x63, 0x55,
                0x16, 0x76, 0x15, 0x93, 0xF7, 0xA5, 0x1D, 0x99, 0xEB, 0x3A,
                0xD4, 0x21, 0xB7, 0x1A, 0x2C, 0x9D, 0xCD, 0xAA, 0x27, 0x2B,
                0x5C, 0x82, 0x1A, 0x76, 0xA7, 0x76, 0x18, 0x5F, 0x00, 0xB4,
                0x63, 0x37, 0x7F, 0x11, 0x40, 0xC5, 0x2C, 0x51, 0x6F, 0xA1,
                0x94, 0xC5, 0x8C, 0x4F, 0xE2, 0xD0, 0xE9, 0xE2, 0xA3, 0x9C,
                0xD5, 0xC2, 0x9C, 0x0A, 0x1D, 0xE6, 0x29, 0x46, 0xE3, 0x29,
                0x71, 0x63, 0xD7, 0x8A, 0x4E, 0xCA, 0x71, 0xAF, 0xDF, 0xF5,
                0xAB, 0x68, 0x4E, 0x47, 0x3A, 0xBC, 0x2F, 0x54, 0x17, 0x16,
                0x74, 0xD6, 0xE5, 0xBB, 0x0D, 0xAD, 0xE3, 0xBB, 0xF7, 0x62,
                0x07, 0x8C, 0xD6, 0xC8, 0x0E, 0x95, 0x0E, 0x88, 0xBA, 0x25,
                0x0F, 0xF8, 0x4C, 0x26, 0x7A, 0x76, 0x14, 0xE0, 0x7C, 0x9A,
                0xEE, 0xC9, 0x8B, 0x5C, 0xD4, 0xF7, 0x9E, 0x5D, 0xDE, 0xAC,
                0x99, 0xB9, 0x13, 0x8E, 0xEC, 0xB2, 0x2D, 0x23, 0x68, 0xEE,
                0xCE, 0x5F, 0x7C, 0x92, 0x5D, 0xA8, 0xE3, 0xC9, 0x6B, 0xB5,
                0x74, 0xAC, 0x12, 0xE7, 0xB6, 0x42, 0xDA, 0x98, 0x28, 0xCD,
                0x58, 0x1C, 0xF1, 0xFC, 0xEE, 0x75, 0x70, 0xF5, 0x78, 0xE6,
                0x76, 0x50, 0x35, 0x6A, 0xD6, 0xD4, 0xB9, 0x5A, 0x10, 0x95,
                0x03, 0x44, 0xB0, 0x1B, 0x59, 0xB9, 0x40, 0xB2, 0x1A, 0x26,
                0x4E, 0x7B, 0xD8, 0x29, 0xD1, 0x23, 0xCD, 0x52, 0xE7, 0xF5,
                0x70, 0x8F, 0xA7, 0x4E
        };
int main()
{
    uint32_t* v = (uint32_t *)ida_chars;
    uint32_t const k[4] = {116, 111, 114, 97 };
    int n= -66; //n的绝对值表示v的长度,取正表示加密,取负表示解密
    // v为要加密的数据是两个32位无符号整数
    // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
    btea(v, n, k);
    for (int i = 0; i < 264; i++)
    {
        ida_chars[i] = ((ida_chars[i] >> 3) & 0XFF) | ((ida_chars[i] << 5) & 0XFF);
    }

    for (int i = 0; i < 264; i++)
    {
        printf("%02x", ida_chars[i]);
    }
    FILE *fshell = fopen("shellcode", "wb");
    fwrite((void *)enc, 4, 66, fshell);
    fclose(fshell);
    
    return 0;
}

在这里插入图片描述

使用shellcodeloader加载shellcode

加载后用IDA动调

在这里插入图片描述

v17

在这里插入图片描述

v22
在这里插入图片描述

脚本求解

import hashlib
str1 = "LoadLibraryExA"
str2 = "is program can"
str3 = ""
flag = "HFCTF{"
for i in range(14):
    str3 += chr(ord(str2[i]) + ord(str1[i]) % 5)
enc = "YPxoTHcmBzPSZItSMItSDItSFItyKA+3SiYz/zPArDxhfAIsIMHPDQP44vBSV4tSEItCPAPCi0B4hcAPhL4AAAADwlCLSBiLWCAD2oP5AA+EqQAAAEmLNIsD8jP/M8Cswc8NA/g6xHX0A3wkBDt8JAx12TP/M8mDwlAPtgQKwc8NA/hBg/kOdfHBzw1XM/8zyYtUJDxSD7YcDrhnZmZm9+vR+ovCwegfA8KNBIAr2FoPtgQKK8PBzw0D+EGD+Q511MHPDTs8JHQWaCVzAACLxGhubwAAVFCLXCRI/9PrFGglcwAAi8RoeWVzAFRQi1wkSP/TWFhYWFhYWFhYYcNYX1qLEukL"
enc += str3
flag += hashlib.md5(enc.encode()).hexdigest() + '}'
print(flag)

参考

https://zzzzsky.com/2022/03/21/2022%E8%99%8E%E7%AC%A6CTF_%E9%83%A8%E5%88%86RE_WP/

https://blog.shi1011.cn/ctf/2259

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值