Sabtu, 29 Juli 2017

ROP 1. Simple Introduction About ROP

untitled

ROP atau kita biasa sebut return oriented programming adalah tingkatan tertinggi dan tersulit dari kategori pwning. Sampai saat ini saya maish belum menguasai dan mempraktikannya. Beberapa gadget masih terlihat asing bagi saya. tapi saya akan berusaha menulis perlahan lahan apa yang saya baru tau dan apabila salah mohon koreksinya ya :).

ROP atua return oriented programming adalah eksploitasi sebuah program dengan mengarahkan EIP atau intsruct pointer ke gadget gadget yang kita sambungkan agar memunculkan suatu fungsi yang kita inginkan. Umumnya tingkatan tertinggi dari eksploit adalah kita mampu memanggil shell dari program yang dieksploit. Gadget adalah kumpulan instruski assembly yang memiliki instruksi ret di akhir agar program kembali ke dalam stack untuk melanjutkan gadget lainnya hingga memanggil shell

Apa yang kita bisa lakukan dengan gadget?

Contoh beberapa penggunaan gadget

  1. Memasukkan sesuatu ke register
  • pop eax, ret + 0xdeadbeef Gadget ini akan mengisi register eax dengan 0xdeadbeef
  1. Membaca dari memori
  • mov ecx, [eax], ret gadget ini akan memasukkan nilai yang berada pada alamat eax ke register ecx
  1. Memasukkan ke memori (stack)
  • mov [eax], ecx, ret

Gadget ini akan memasukkan nilai ecx ke alamat memori yang ditunjuk eax

  1. Aritmatika

add eax, 0x0b, ret

Ini akan menambahkan eax senilai 0x0b

xor eax, eax

mengosongkan nilai eax

  1. System call

int 0x80, ret

call gs:[0x10], ret

GADGET YANG HARUS DIHINDARI

gadget yang mengandung pop ebp, semua akan merusak stack Payload tidak boleh mengandung nullbytes

Untuk memanggil shell, kita harus memvariasikan beberapa chainig dari rop gadget, sehingga kita, bisa memanggil call system dengan argumen /bin//sh

Satu chaining yang saya pelajari untuk memanggil shell

  1. xor eax, eax ; untuk mengosongkan eax
  2. menulis /bin/sh didalam memori yang paling aman. Kita cbba untuk untuk menulis nya didata segmen. Yang dapat kita lakukan adalah menggunakan gadget
  • pop {REG1}, ret, ALAMAT
  • pop {REG2}, ret, STRING
  • mov [REG1], REG2

Lakukan dua kali. Karena string /bin//sh memiliki ukuran 8 byte. Kita.

  1. Setelah semua persiapan selesai, kita bisa memanggil function call dengan gadget
  • xor eax, eax ; untuk mengosongkan eax
  • add eax, 0x0b ;mengisi eax, dengan function system call
  • call gs:[0x10], ret

Payload ROP dari berbagai macam soal, bisa bervarisi, dari gadget gadget yang tersedia dari program

Beberapa payload yang pernah saya temui baik dari baca baca payload orang lain.

  • Buffer + pop eax, pop ecx , ret + u32("/bin") + p32(0xaddr) + mov [eax], ecx, ret + xor eax, eax , ret + add eax, 0x0b, ret + call gs:[0x10], ret

Postingan ini pasti akan dilanjuti untuk meneruskan apa yang saya sudah pelajari dari ROP

Reversing 1. Simple XOR

untitled

Reversing 1. Membaca Pseudocode, dan reverse langsung

Kali ini kita akan membahas sedikit tentang reverse engineering. Reverse engineering adalah Ilmu untuk merekonstruksi program dari program yang sudah dicompiled, menjadi pseudocode, dan memahami pseudocode tentang bagaimana program tersebut bekerja. Didalam dunia cyber security. Reversing adalah tingkat tertinggi bersamaan dengan binary eksploitation. Banyak manfaat yang dapat kita dapatkan jka kita belajar reverse engineering, kita dapat melihat suatu program bekerja apakah dia bekerja sebagai mana mestinya, atau ada kesalahan / bug / illegal instruction yang disisipkan pada program tersebut. Kemampuan reverse engineering juga dapat membantu bidang security lain seperti membaca suatu program yang mengenkripsi dengan menggunakan suatu metode kriptografi, dan juga membantu membaca kelemahan program yang dapat dieksploit. Tanpa kemampuan reverse engineering, kemungkinan kita bisa mengeksploit program sangat kecil bahkan mendekati nl.

Untuk belajar reverse engineering, kita membutuhkan kemampuan untuk memahami source code, dan tentu kemampuan coding. Untuk reverse engineerin tingkat atas, tentu kita juga membutuhkan kemampuan menggunakan dan memahami assembly, namun saya juga masih banyak belajar untuk assembly, jadi kita belum akan membahasnya disini.

Kali ini kita akan menggunakan soal dari slashroot CTF yang masing hangat yaitu soal Phunpack. (Binary diupload oleh Fanpage Cyber security IPB).

Seperti biasa, kita harus mengidentifikasi terlebih dahulu binary tersebut.

alfakatsuki@justPC:/media/sda6/CTF (All)/CTF Events/FINAL SLEZRUT/REVERSING$ file phunpack
phunpack: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.24, BuildID[sha1]=5bed9389e4ebb4a335c343185f4beec6fe31e741, not stripped
alfakatsuki@justPC:/media/sda6/CTF (All)/CTF Events/FINAL SLEZRUT/REVERSING$ checksec phunpack
[*] '/media/sda6/CTF (All)/CTF Events/FINAL SLEZRUT/REVERSING/phunpack'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
alfakatsuki@justPC:/media/sda6/CTF (All)/CTF Events/FINAL SLEZRUT/REVERSING$ ./phunpack
Enter the password: aaaaaaaaaaaa
No no no!
alfakatsuki@justPC:/media/sda6/CTF (All)/CTF Events/FINAL SLEZRUT/REVERSING$ ./phunpack
Enter the password: a
No no no!
alfakatsuki@justPC:/media/sda6/CTF (All)/CTF Events/FINAL SLEZRUT/REVERSING$ ./phunpack
Enter the password:
No no no!
alfakatsuki@justPC:/media/sda6/CTF (All)/CTF Events/FINAL SLEZRUT/REVERSING$

Bisa kita lihat bahwa program meminta kita untuk memberikan input berupa password dan jika salah akan memunculkan hasil tersebut.

Mari kita coba decompile dengan IDA 64 bit atau decompiler lain. Namun kali ini kita coba IDA karena hasil decompile yang paling mudah dibaca.

Berikut adalah layout pemanggilan Fungsi pada program.

Kita coba decompile fungsi Main.

Berikut adalah pseudocode C dari fungsi main

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int result; // eax@4
  __int64 v4; // rcx@4
  char v5; // [sp+10h] [bp-20h]@1
  __int64 v6; // [sp+28h] [bp-8h]@1

  v6 = *MK_FP(__FS__, 40LL);
  printf((unsigned __int64)"Enter the password: ");
  fgets(&v5, 11LL, stdin);
  if ( passcheck(&v5) == 10 )
    printf((unsigned __int64)"Correct flag! SlashRootCTF{%s}\n");
  else
    puts("No no no!");
  result = 0;
  v4 = *MK_FP(__FS__, 40LL) ^ v6;
  return result;
}

Kita tau bahwa fungsi fgets meminta kita untuk meminta sebuah inputan dan dimasukkan kedalam variabel v5. Untuk mendapatkan flag yang benar kita harus fungsi passcheck yang memiliki argumen v5 tadi harus return nilai 10,

Mari kita decompile fungsi passcheck dan lihat pseudo code nya.

__int64 __fastcall passcheck(__int64 a1)
{
  __int64 v1; // rax@1
  __int64 result; // rax@8
  __int64 v3; // rcx@8
  unsigned int v4; // [sp+18h] [bp-28h]@1
  signed int i; // [sp+1Ch] [bp-24h]@2
  char v6; // [sp+20h] [bp-20h]@1
  char v7; // [sp+21h] [bp-1Fh]@1
  char v8; // [sp+22h] [bp-1Eh]@1
  char v9; // [sp+23h] [bp-1Dh]@1
  char v10; // [sp+24h] [bp-1Ch]@1
  char v11; // [sp+25h] [bp-1Bh]@1
  char v12; // [sp+26h] [bp-1Ah]@1
  char v13; // [sp+27h] [bp-19h]@1
  char v14; // [sp+28h] [bp-18h]@1
  char v15; // [sp+29h] [bp-17h]@1
  __int64 v16; // [sp+38h] [bp-8h]@1

  v16 = *MK_FP(__FS__, 40LL);
  v4 = 0;
  v6 = 85;
  v7 = 110;
  v8 = 80;
  v9 = 65;
  v10 = 67;
  v11 = 75;
  v12 = 70;
  v13 = 84;
  v14 = 87;
  v15 = 33;
  LODWORD(v1) = strlen();
  if ( v1 == 10 )
  {
    for ( i = 0; i <= 9; ++i )
    {
      if ( *(_BYTE *)(i + a1) == *(&v6 + i) ) #### Penting
        ++v4;
      else
        v4 = 0;
    }
  }
  result = v4;
  v3 = *MK_FP(__FS__, 40LL) ^ v16;
  return result;
}

Fungsi passcheck mereturn nilai result. Nilai result didapat dari membandingkan tiap char pada argumen dari passcheck dengan char yang ada pada local variabel, yaitu char dari alamat v6. Apabila i sudah mencapai 10 maka program akan dia break.

Inputan kita dibandingkan dengan isi dari variabel v4 - v15. Kita tinggal membuat skrip python sederhana atau manual pun juga bisa untuk mengubah nilai int yang disana menjadi jilai char. Namun sekalian untuk belajar programming mari kita coding.

import re
from pwn import *
dump = """v6 = 85;
v7 = 110;
v8 = 80;
v9 = 65;
v10 = 67;
v11 = 75;
v12 = 70;
v13 = 84;
v14 = 87;
v15 = 33;"""

dump = dump.split('\n')

passs = ""

for i in dump :
  a = re.search('= (.+?);', i)
  passs += chr(eval(a.group(1)))

print passs
# p = process('./phunpack')
# p.recvline('password: ')
# p.sendline('passs')
# p.recvline()
# p.recvline()
# p.kill()

Skrip diatas itu kita sekalian submit ya. Lumayan sekalian belajar pwning juga. Tapi akhirnya saya ga jadi make karena ga tau kenapa binary nya ga bisa dipwn.

Didapat string 'UnPACKFTW!'. Ayo kita coba masukkan dipassword

alfakatsuki@justPC:/media/sda6/CTF (All)/CTF Events/REVERSING$ ./phunpack
Enter the password: UnPACKFTW!
Correct flag! SlashRootCTF{UnPACKFTW!}

Ternyata benar flagnya :D.

Jika kita melihat hasil dari pseudocode maka terlihat rumit sekali, namun ternyata hanya dibandingkan saja. Karena itu kita harus menguasai bahasa pemrograman untuk bisa melihat dan mengidentifikasi mana code code yang penting agar untuk kita reverse. :)

Sekian dari saya. Pada postingan kedepan, kita akan mencoba untuk mereversing dengan metode bruteforcing. Semoga bermanfaat.

Kamis, 20 Juli 2017

Make the bot 2. Beat captcha


Jika sebelumnya kita mencoba mengalahkan program executables, kali ini kita akan coba belajar bagaimana untuk membuat bot yang bekerja pada web.

Sebagai bahan belajar php saya, saya mencoba untuk membuat web pengisian captcha boong boongan. Karena saya hanya menuliskan angka captcha nya di web tersebut. Untuk mendapatkan flag, Kita harus memasukkan angka pada captcha sebanyak 500 kali.

1

Apabila kita memasukkan captcha maka

2

Web captcha tersebut dapat diakses di (will be added soon). Jika kalian ingin menjalankan web captcha ini di local, saya memberikan source code web tersebut bisa dilihat dibawah ini.

index.php

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Captcha Idiotequie</title>
  </head>
  <body>
    <?php
    $stat = file_get_contents('status');
    echo "This is your captcha ". $stat." \n";
    ?>
    <form action="receive.php" method="post">
      <input type="text" name="captcha">
      <input type="submit" name="login">
    </form>
  </body>
</html>

receive.php

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Receive</title>
  </head>
  <body>
    <?php
    $count = file_get_contents('counts');
    $stat = file_get_contents('status');
    $input = $_POST['captcha'];
    if($count>=500){
      echo "YES YOUR THE WINNER\n";
      echo "FLAG_HERE\n";
    }
    else if($stat===$input){
      echo "yes youre right". "\n";
      $newstat = fopen('counts', 'w');
      $more = 500-$count;
      echo "You need ". $more ." More\n";
      fwrite($newstat, $count+1);
      fclose($newstat);
    } else {
      echo "Try again dude\n";
    }
    $stat = fopen('status', 'w');
    $acak = rand();
    fwrite($stat, $acak);
    fclose($stat);
    ?>
  </body>
</html>

Dapat dilihat pada source code. Di index.php, kita akan mendapatkan nomor captcha yang diakses dari file status, lalu ditampilkan. Kita diharuskan untuk mengisi nomor tersebut dan mensubmit dengan metode post, agar di terima oleh receive.php. Di receive.php, inputan di cocokkan dengan file status tadi, setelah itu, isi dari file status itu dirubah dengan angka random kembali.

Karena itu bot yang kita buat harus mengambil nomor dari index.php lalu mengirimkannya dengan metode post ke parameter 'captcha' secara terus menerus.

Berikut adalah skrip python yang kita gunakan untuk menyelesaikan soal

import re
import requests


for i in range(0, 503):
    urlkirim = "http://localhost/captchaproject1/receive.php"
    urlambil = "http://localhost/captchaproject1/index.php"
    a  = requests.get(urlambil)
    print a.content
    num = re.search('captcha (.+?) ', a.content)
    number = num.group(1)
    b = requests.post(urlkirim, data={'captcha':str(number), 'login':'Submit'})
    print b.content

Kita coba jalankan di terminal.

alfakatsuki@justPC:~/Desktop$ python exploit.py
.
.
.
.
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Receive</title>
  </head>
  <body>
    YES YOUR THE WINNER
    CTF{DiDnt_NeeD_TENsoR_FLOW_to_Solve_THIS}
    yes youre right
You need -9 More
  </body>
</html>

alfakatsuki@justPC:~/Desktop$

Setelah menunggu beberapa saat, kita berhasil mendapatkan flagnya yaitu CTF{DiDnt_NeeD_TENsoR_FLOW_to_Solve_THIS}. Metode request sederhana dan mengekstrak data seperti ini sangat berguna baik untuk CTF ataupun untuk mengirimkan data atau mengambil data secara otomatis.

Cukup sekian cara sederhana untuk menggunakan python untuk membuat request pada halaman web. Semoga dapat bermanfaat bagi kita semua :).

Kriptografi 3. MD5 dan Hashing

MD5 dan Hashing
Jika sebelumnya kita membahas tentang enkripsi kali ini kita akan membahas salah satu jenis hashing yaitu md5. Hashing adalah suatu formula, atau suatu algoritma satu arah untuk mengidentifikasi suatu data. Dua tipe data yang identik memiliki hash yang sama. Yang berbeda antara hashing dengan enkripsi adalah hasil hash tidak dapat dikembalikan menjadi data awal. Sehingga hashing disebut dengan algoritma satu arah. Ada banyak hashing yang biasa kita temui, kali ini kita akan membahas tentang MD5.
Hash MD5 berukuran 16 byte. Jika kita mengubah satu karakter saja pada string yang di hash, maka hash akan berbeda sangat jauh, sehingga hash md5 dapat digunakan untuk mendeteksi kerusakan pada file.
Dengan menggunakan bash
alfakatsuki@justPC:~$ echo -n 'a' | md5sum
0cc175b9c0f1b6a831c399e269772661  -
Dengan menggunakan python
import hashlib
print hashlib.md5("a").hexdigest()
Sebagai contoh penggunaan md5 untuk mendeteksi kerusakan file adalah sebagai berikut. Saya akan membuat file bernama testbinary.txt
alfakatsuki@justPC:~$ echo 'AAAAAAAAAA' > testbinary.txt
alfakatsuki@justPC:~$ cat testbinary.txt
AAAAAAAAAA
testbinary.txt berisi 10 karakter A dan diakhiri newline diakhir. Kita cari md5sum nya menggunakan bash saja.
alfakatsuki@justPC:~$ md5sum testbinary.txt
86d48f739677a6bc11751a9a3fd4a0d1  testbinary.txt
Kita coba kalau satu karakter tadi B nya
alfakatsuki@justPC:~$ echo 'AAAAAAAAAB' > testbinary.txt
alfakatsuki@justPC:~$ cat testbinary.txt
AAAAAAAAAB
alfakatsuki@justPC:~$ md5sum testbinary.txt
5542eaca4309f3aa71bf384f23eeb966  testbinary.txt
Hash yang dihasilkan sangat jauh berbeda.
Hash juga digunakan untuk menyimpan password sehingga pihak server pun tidak mengetahui password yang sebenarnya. Password yang dikirim user, dihash, dan hash tersebut disimpan sebagai pencocok apabila user akan login. Sehingga apabila server diserang, keamanan pengguna masih tetap terjaga.
Namun walaupun tidak dapat direverse, hash masih bisa dikembalikan dengan metode bruteforce. Kumpulan word di hash lalu disimpan di internet sebagai database dari word sebelum dihash. Begitulah cara decrypt md5 bekerja dengan mencocokan hash md5 dengan database hash yang dimiliki oleh web tersebut.
Namun beberapa password menggunakan padding atau karakter sampah pada plain text sehingga tidak akan didapat hash yang sama pada database. Kita akan mencoba menyelesaikan soal sederhana untuk mendekrip hash yang memiliki padding.

Quest.

Saya memiliki hash 596d4043ad79fc82e7f496daff8dc8e9. String asli dari hash ini adalah "SARAPANKUY" dengan padding 1 byte di kiri dan satu byte dikanan string. Tugas kita adalah mengirim flag padding yang digunakan dengan format CTF{"hexapaddingkiri"+"hexapadingkanan"}. Contoh jawaban. CTF{'\x41\x41'}
Kita dapat menggunakan python untuk membruteforce byte tersebut. Byte berkisar dari 0x00 sampai 0xff.
import hashlib
string = "SARAPANKUY"
hashtrue = "596d4043ad79fc82e7f496daff8dc8e9"
kelar = 0
#untuk membruteforce byte kiri
for i in range(0x00, 0xff):
  if kelar == 1:
    break
  #untuk membruteforce byte kanan
  for j in range(0x00, 0xff):
    if kelar == 1 :
      break
    stringbaru = chr(i) + string + chr(j)
    hashbaru = hashlib.md5(stringbaru).hexdigest()
    print hex(i), hex(j), hashbaru, hashtrue
    if hashbaru == hashtrue:
      kelar = 1
# 0x99 0x99 596d4043ad79fc82e7f496daff8dc8e9 596d4043ad79fc82e7f496daff8dc8e9
Kita berhasil mendapatkan flagnya. yaitu '\x99' dan '\x99'. CTF{'\x99\x99'}
Sekian yang dapat saya bagikan. Semoga bermanfaat bagi kita semua :).

Rabu, 19 Juli 2017

Kriptografi 2. RSA

untitled

Jika kemarin kita membahas tentang enkripsi dan dekripsi linier, kali ini kita akan membahas salah satu sistem enkripsi asimetris, yaitu RSA. Sedikit sejarah RSA diciptakan oleh 3 orang matematikawan, bernama (Rivest - Shamir - Adleman).

Berbeda dengan enkripsi simetris yang menggunakan kunci yang sama untuk mendekripsi ataupun mengenkripsi, RSA memiliki 2 kunci. Yang pertama kunci publik yang disebar luas yang dapat digunakan untuk mengenkripsi suatu data. Dan yang kedua kunci private, yang dirahasiakan, yang dapat digunakan untuk mendekripsi chiper text menjadi plain text.

Langkah langkah untuk melakukan enkripsi dengan RSA adalah sebagai berikut.

  1. Kita harus memilih dua angka prima yang besar dan memiliki jarak berjauhan. Kita simbolkan dua angka prima ini sebagai p dan q. Bilangan prima ini harus dirahasiakan.
  2. Hitung nilai n atau yang disebut dengan modulus yang merupakan p * q.
  3. Hitung nilai euler dari p dan q. Nilai ini dapat disimbolkan sebagai Etha, Etha = (p-1) * (q - 1)
  4. Bangkitkan nilai e yang digunakan untuk menenkripsi pesan. Nilai e dapat dicari dengan gcd(etha, e) = 1. (gcd atau great common divisor adalah fpb :))
  5. Bangkitkan nilai d yang digunakan untuk mendekripsi pesan. Nilai d dapat dicari dengan syarat d = e^-1 mod etha. Sederhananya kita harus mencari d * e yang ketika di mod oleh etha maka hasilnya adalah 1 :). Kita akan bahas kembali menggunakan contoh soal nanti.

Kita sudah berhasil mendapat dua kunci untuk melakukan enkripsi ataupun melakukan dekripsi menggunakan RSA.

Jika kita memiliki M sebagai plain text dan C sebagai chiper text. Maka

  1. Untuk melakukan enkripsi kita menggunakan rumus
C = (M ^ e) mod n
  1. Untuk melakukan dekripsi kita menggunakan rumus
M = (C ^ d) mod n

Biasanya kita menggunaknan library Crypto.Util.number sebagai library untuk mempermudah kita menggunakan RSA sebagai Kriptografi

Mari kita coba lakukan enkripsi dan dekripsi menggunakan RSA.

  1. Kita memiliki plain text INI RAHASIA YA.
  2. Kita rubah plain text kita menjadi long integer. Seperti biasa kita gunakan bahasa favorit kita yaitu python
from Crypto.Util.number import *
M = bytes_to_long("RAHASIA")
# 23152726679701825L
  1. Kita harus menjadi dua bilangan prima. Untuk contoh kita gunakan bilangan prima sederhana.
p = getPrime(50)
# 918672504821917L
q = getPrime(60)
# 1049954349787377767L
  1. Kita mencari nilai modulus(n) dengan mengalikan p dan q.
n = p * q
  1. Cari nilai euler dari n.
etha = (p-1)*(q-1)
  1. Kita cari nilai e untuk mengenkripsi. Kita pilih e adalah 31337
e = 31337
GCD(31337, etha)
# 1
  1. Kita cari nilai d untuk mendekripsi.
d = inverse(e, etha)
  1. Kita telah memiliki segala komponen untuk melakukan enkripsi maupun dekripsi menggunakna RSA. Mari kita lakukan enkripsi.
C = pow(M, e, n)
# 300067976514851794302918890099634L
  1. Nilai 300067976514851794302918890099634L adalah hasil dari enkripsi plain text kita. Untuk melakukan dekripsi.
M = pow(C, d, n)
print M
print long_to_bytes(M)
# 'RAHASIA'

Kita berhasil melakukan enkripsi dan dekripsi menggunakan RSA. RSA cukup efektif digunakan apabila nilai modulus yaitu n tidak dapat difaktorkan dengan mudah. Serangan terhadap RSA dilakukan dengan berusaha memfaktorkan nilai n agar didapat nilai p dan q. Jika kita berhasil memfaktorkan nilai n dan mendapatkan nilai p dan q maka kita dapat mendekripsi chiper text tanpa harus mengetahui private key.

Skrip lengkap dapat dilihat dibawah ini ya.

from Crypto.Util.number import *
M = bytes_to_long("RAHASIA")
p = getPrime(50)
q = getPrime(60)
n = p * q
etha = (p-1)*(q-1)
e = 31337
d = inverse(e, etha)
C = pow(M, e, n)
print C
#ini adalah chiper text
M = pow(C, d, n)
print long_to_bytes(M)
#kita kembalikan kembali chiper text menjadi plain text

Note : Seluruh proses pada RSA menggunakan angka, sehingga kita harus mengubah type data yang ingin dienkripsi menjadi angka.

Sekian postingan kali ini semoga bermanfaat :).