Henry Isakoff 🥕 Sovellusten Hakkerointi

| Sovellusten Hakkerointi | 7 min

Säieet ohjelmistoon.

Tässä raportissa tutustumme binäärien sisältöön, strings komennon kautta. Lisäksi tutustumme binääriin rammissa ja c-kieleen.

ezbin-challenges

Opettajan binäärit saamme ladattua hänen sivulta. Suora linkki on tässä, mutta ikuista varmuutta zip tiedostoon ei ole. Varoituksen sana.

Ensimmäisenä tutustumme ’strings’ haasteeseen. Lataus wgetillä, unzip ja kansion sisään.

Saamme binäärin ’passtr’. Ajan file komennolla.

file passtr

passtr: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=ceddb0a2caba0d00947ffcb1883ad738aa8b9f07, for GNU/Linux 3.2.0, not stripped

Tässä näemme, että binääri on ”not stripped”, eli sen voi ajaa debuggerilla tai disasseblerissa. Nyt tässä ei kuitenkaan sille tarvetta.

Etsimme salasanaa ohjelmassa joten yksinkertaisesti ajan

strings passtr | grep pass

Tämä tuo ensimmäisenä FLAG arvon eteen ja ”What’s the password?”. Otetaan rivit mukaan molemmilta puolilta.

strings passtr | grep -A 1 -B 1 pass

Kokeilu

Tästä löytyy sala-hakkeri-321

Kokeillaan vielä ajaa.

Sisältö

Korjataan C-binääri

C-on itselleni suht vieras kieli, mutta olen tässä disobeyn tehtäviin juuri opetellut XOR-obfuskoinnista. Eli sotkemme salasanan bitin-vakio luvulla (obfuskointi). Näin strings ei ymmärrä koodia, eikä näytä sitä.

Alkuperäinen koodi

#include <stdio.h>
#include <string.h>

int main() {
        char password[20];

        printf("What's the password?\n");
        scanf("%19s", password);
        if (0 == strcmp(password, "sala-hakkeri-321")) {
                printf("Yes! That's the password. FLAG{Tero-d75ee66af0a68663f15539ec0f46e3b1}\n");
        } else {
                printf("Sorry, no bonus.\n");
        }
        return 0;
}

Lisäämme vakion (define) avain joka vaikka arvolla 0x42 (66) joka ajetaan ennen kuin koodi käännetään c:ssä. Luodaan myös salasanan jokaiselle merkille avaimen (0x42) vakio mukaan. Jolloin salasana kokonaisuudessaan obfuskoidaan.

Arvot piilo_sanasala ja piilo_libbu obfuskoi arvot ja oikea_sanasala/oikea_libbu palauttavat taulukot oikeaan arvoon.

Tämän käännös kääntää salasanan takaisin ennen lukua.

Muutin myös koodin termistön omaan lukuun helpommaksi ’duh’.

Käytin xor-arvoissa ja koodin pohjassa apuna mistral-small3.2 LLM apuna. Koodissa oli paljon vikaa joten korjasin pohjakoodia todella paljon. Epäilin, että myös xor avaimessa olisi, mutta siitä kohta lisää /retrospect/.

#include <stdio.h>
#include <string.h>

int main() {
  char password[20];
  unsigned char piilo_sanasala[] = {
      0x31, 0x21, 0x2e, 0x21, 0x6b, 0x2a, 0x21, 0x2d, 0x2d, 0x27,
      0x30, 0x2b, 0x6b, 0x71, 0x70, 0x73
  };
  unsigned char piilo_libbu[] = {
        0x04, 0x0e, 0x03, 0x05, 0x39, 0x16, 0x27, 0x30, 0x2d, 0x6f,
        0x26, 0x75, 0x77, 0x27, 0x27, 0x74, 0x74, 0x23, 0x24, 0x72,
        0x23, 0x74, 0x7a, 0x74, 0x74, 0x71, 0x24, 0x73, 0x77, 0x77,
        0x71, 0x7b, 0x27, 0x21, 0x72, 0x24, 0x76, 0x74, 0x27, 0x71,
        0x20, 0x73, 0x3f
  };
	
	unsigned char avain = 0x42;
  printf("What's the password?\n");
  scanf("%19s", password);

  size_t sanasala_pituus = sizeof(piilo_sanasala);
  char salis[64];
  for (int i = 0; i < sanasala_pituus; i++) {
    salis[i] = piilo_sanasala[i] ^ avain;
  }
  salis[sanasala_pituus] = '\0';

  if (0 == strcmp(password, salis)) {
    printf("Yes! That's the password. ");

    size_t libbu_pituus = sizeof(piilo_libbu);
    char lippu[64];
    for (int i = 0; i < libbu_pituus; i++) {
      lippu[i] = piilo_libbu[i] ^ avain;
    }
    lippu[libbu_pituus] = '\0';
    printf("%s\n", lippu);
  } else {
    printf("Sorry, no bonus.\n");
  }

  return 0;
}

Tämän jälkeen ajan uuden koodin c-compilerin läpi ja tarkastan, että se toimii.

gcc -o passtr.obf passtr.obf.c /.passtr.obf

Kokeilu

Thoimii! Paitsi ei toimi. Ohjelma ei toimi enää toiseen suuntaan. Epäilen, että mistrall on tehnyt XOR taulukossa virheen, mutta sen sijaan, että tarkastan taulukon - teen pienen debuggerin.

Tunnen koodin niin helppo on ajaa oma taulukko uudestaan, verrata purettuun salasanaan ja oikeaan salasanaan.

#include <stdio.h>
#include <string.h>

int main() {
    unsigned char piilo_sanasala[] = {
        0x31, 0x21, 0x2e, 0x21, 0x6b, 0x2a, 0x21, 0x2d, 0x2d, 0x27, 
        0x30, 0x2b, 0x6b, 0x71, 0x70, 0x73
    };
    
    unsigned char avain = 0x42;
    
    printf("Purettu salasana: '");
    for (int i = 0; i < sizeof(piilo_sanasala); i++) {
        char merkki = piilo_sanasala[i] ^ avain;
        printf("%c", merkki);
    }
    printf("'\n");
    
    char oikea[] = "sala-hakkeri-321";
    printf("Oikea salasana:   '%s'\n", oikea);
    
    printf("Oikeat XOR-arvot: ");
    for (int i = 0; i < strlen(oikea); i++) {
        printf("0x%02x, ", (unsigned char)(oikea[i] ^ avain));
    }
    printf("\n");
    
    return 0;
}

Laitan mukaan myös oikeat XOR arvot printtamaan. Tämä hyvä huijaus-pöytä jos jatkossa ongelmia näiden kanssa. Nimittäin tässä näitä tullut ja huomaan jatkuvasti etsiväni omista muistiinpanoista ohjauksia 😂

./debug Purettu salasana: 'sclc)hcooeri)321' Oikea salasana: 'sala-hakkeri-321' Oikeat XOR-arvot: 0x31, 0x23, 0x2e, 0x23, 0x6f, 0x2a, 0x23, 0x29, 0x29, 0x27, 0x30, 0x2b, 0x6f, 0x71, 0x70, 0x73,

Kokeilu

Sieltähän tuo löytyi. Korjataan koodiin suoraan tuosta. Vastaavan olisin voinut tehdä FLAG arvolle, mutta se jostain syystä oikein.

Live love laugh.

  unsigned char piilo_sanasala[] = {
      0x31, 0x23, 0x2e, 0x23, 0x6f, 0x2a, 0x23, 0x29, 0x29, 0x27, 
      0x30, 0x2b, 0x6f, 0x71, 0x70, 0x73
  };

Thoimii!

Kokeilu

Packd ja haetaan rammista.

Olen tässä tutustunut edellisen viikon aikana hex koodiin rammista (disobey tehtävä) ja samalla on tullut vastaan uusia työkaluja. Näistä apua tässä.

Katsotaan Teron seuraavaa binääriä.

> file packd
packd: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), statically linked, no section header

> strings packd | grep -A 1 -B 1 pass
u+UH
What's the password?
piilos-An

Tässä huomataan, että salasana on piilossa. Äkkiseltään piilos-An tai ’What’s the password?’ arvojen lähelle.

Me siis voidaan ajaa prosessi rammista suoraan kätevällä python lisäkirjastolla pwndbg. Asennusohjeet tässä. Eli me voidaan etsiä merkkijonoja itse prosessista suoraan RAM-muistista. Huikean kätevää.

Ajan prosessin tmuxilla käyntiin pohjalle, erotan ikkunan ja etsin prosessin PID numeron jonka voin lähettää eteenpäin.

 ps -aux | grep packd
henry      12713  0.0  0.0   2564  1280 pts/2    S+   01:43   0:00 ./packd

pwndbg -p 12713

Tässä voimme etsiä pwndbgllä arvojen läheltä missä kohtaa tuo ’What's the password?’ on.

Saamme vastaukseksi kohdan anon_7f86c10bb. Joka voidaan hexdumpata pwndbgn sisällä.

pwndbg> search -t string "What's the password?"
Searching for string: b"What's the password?\x00"
[anon_7f86c10bb] 0x7f86c10bb008 "What's the password?"
packd           0x7f86c10bf560 "What's the password?"

pwndbg> hexdump anon_7f86c10bb
+0000 0x7f86c10bb000  01 00 02 00 00 00 00 00  57 68 61 74 27 73 20 74  │........│What's.t│
+0010 0x7f86c10bb010  68 65 20 70 61 73 73 77  6f 72 64 3f 00 25 31 39  │he.passw│ord?.%19│
+0020 0x7f86c10bb020  73 00 70 69 69 6c 6f 73  2d 41 6e 41 6e 41 73 00  │s.piilos│-AnAnAs.│
+0030 0x7f86c10bb030  59 65 73 21 20 54 68 61  74 27 73 20 74 68 65 20  │Yes!.Tha│t's.the.│

Ja tämä tuo arvon ’piilos-AnAnAs’

Kokeillaan sitä.

Kokeilu

Ratkaistu!

Lähteet

Teron binäärit https://terokarvinen.com/sovellusten-hakkerointi/

Dokumentissa käytetty apuna c-koodissa ja XOR salauksessa ja väärin tehdyn XOR salauksen debuggauksessa (heheh) LLM mistra-small3.2:24b mallia. Rautana käytössä ollut Macbook pro m2 max 64gb ja kääntäjänä LM-studio. https://huggingface.co/mistralai/Mistral-Small-3.2-24B-Instruct-2506 https://lmstudio.ai

Pwndbg https://github.com/pwndbg/pwndbg

Kuvat optimoitu https://optimage.app

Käytetty aika 2h 30min