aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md4
-rw-r--r--doc/htbt.md44
-rw-r--r--doc/img/proone.svg65
-rw-r--r--doc/puml/proone-comp.puml34
-rw-r--r--doc/sws.md377
5 files changed, 513 insertions, 11 deletions
diff --git a/README.md b/README.md
index b7fc35c..bc26463 100644
--- a/README.md
+++ b/README.md
@@ -36,12 +36,12 @@ software is programmed to do something illegal! If you wish to use this
software, please do so in a controlled environment safely isolated from the
Internet.
-## Index of Documents
+## Index
Where to go from here
* [User Guide](doc/user_guide.md)
* [Software Design Spec](doc/sws.md)
-* [Protocol Spec](doc/proto.md)
+* [Heartbeat Protocol Spec](doc/htbt.md)
* [Dev Notes](doc/dev_notes.md)
## Subprojects
diff --git a/doc/htbt.md b/doc/htbt.md
index 11f1ed0..2034adc 100644
--- a/doc/htbt.md
+++ b/doc/htbt.md
@@ -30,8 +30,6 @@ indicates the end of the session.
The framinig protocol is designed so that multiple sessions can be pipelined
into a single TCP/IP connection or a DNS TXT record stream.
-
-
## Other Characteristics
* Heartbeat Protocol is a big-endian protocol
* Frames are not aligned to minimise "packet footprint"
@@ -60,6 +58,48 @@ value of TXT records. The
spec([rfc1035](https://datatracker.ietf.org/doc/html/rfc1035#section-3.3) does
not impose such restriction.
+The subthread called "CNC probe worker(CNCP)" of the heartbeat worker runs CNC
+instructions by querying the CNC TXT REC periodically. The interval is hardcoded
+to 1800±1800 seconds. The value of the header record is configured with the
+macro `PRNE_CNC_TXT_REC` and defined as:
+
+```re
+([0-9a-fA-F]{8})(.*)
+```
+
+The first capture group is the number of the data records in hexadecimal with
+leading zeros. The second capture group is the suffix of the data records.
+The name of data TXT records can be constructed like so:
+
+```c
+for (uint32_t i = 0; i < nb_rec; i += 1) {
+ printf("%08X%s", i, suffix);
+}
+```
+
+Where
+
+* *nb_rec* is the number of the data records
+* *suffix* is the suffix of the data records
+
+The CNCP worker will query the data records sequentially from 0th record to get
+the base64 encoded binary data. The stream of base64 data is then decoded and
+fed into a submissive heartbeat context for process.
+
+For example, if the value of the header record is `00000003.cnc.test`, the
+following series of data records are queried.
+
+* `00000000.cnc.test`
+* `00000001.cnc.test`
+* `00000002.cnc.test`
+
+Note that the suffix does not have to start with a dot. And the records from
+different domains can be involved. For example, the name of the header record
+can be "cnc.mydomain.example" and the value "0000000F.otherdomain.example".
+Multiple values of the header record may be defined to achieve load balancing.
+However, a data record must have only 1 value otherwise the CNCP worker will
+regard it as a protocol error.
+
Only public DNS servers which support DNS over TLS are used to counter lawful
interception. The rationale behind this is that the DNS protocol is not
encrypted and ISPs or law enforcfements can easily filter out TXT REC CNC
diff --git a/doc/img/proone.svg b/doc/img/proone.svg
new file mode 100644
index 0000000..00555cd
--- /dev/null
+++ b/doc/img/proone.svg
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="553px" preserveAspectRatio="none" style="width:1006px;height:553px;background:#FFFFFF;" version="1.1" viewBox="0 0 1006 553" width="1006px" zoomAndPan="magnify"><defs><filter height="300%" id="fyc6o7633s18l" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><!--MD5=[9c764811e359eb79ee69534d40b7ac6f]
+cluster prne_i--><polygon fill="#FFFFFF" filter="url(#fyc6o7633s18l)" points="16,115,151,115,158,137.2969,755,137.2969,755,437,16,437,16,115" style="stroke:#000000;stroke-width:1.5;"/><line style="stroke:#000000;stroke-width:1.5;" x1="16" x2="158" y1="137.2969" y2="137.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="129" x="20" y="129.9951">Proone Instance</text><!--MD5=[8ef77d0fb31372a32407c76568343a29]
+cluster Heartbeat--><rect fill="#FFFFFF" filter="url(#fyc6o7633s18l)" height="109" style="stroke:#000000;stroke-width:1.5;" width="340" x="391" y="158"/><rect fill="#FFFFFF" height="10" style="stroke:#000000;stroke-width:1.5;" width="15" x="711" y="163"/><rect fill="#FFFFFF" height="2" style="stroke:#000000;stroke-width:1.5;" width="4" x="709" y="165"/><rect fill="#FFFFFF" height="2" style="stroke:#000000;stroke-width:1.5;" width="4" x="709" y="169"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="78" x="522" y="183.9951">Heartbeat</text><!--MD5=[941875f88b4f76c76a8e027d9b948182]
+cluster bne_pool--><rect fill="#FFFFFF" filter="url(#fyc6o7633s18l)" height="97" style="stroke:#000000;stroke-width:1.5;" width="132" x="244" y="316"/><rect fill="#FFFFFF" height="10" style="stroke:#000000;stroke-width:1.5;" width="15" x="356" y="321"/><rect fill="#FFFFFF" height="2" style="stroke:#000000;stroke-width:1.5;" width="4" x="354" y="323"/><rect fill="#FFFFFF" height="2" style="stroke:#000000;stroke-width:1.5;" width="4" x="354" y="327"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="69" x="275.5" y="341.9951">BNE Pool</text><!--MD5=[7c9481bd1a7d8f3a175620bb8a866d7c]
+cluster Public DOT Nameservers--><path d="M789.4788,326.066 C792.5835,320.581 797.1448,319.113 801.4717,324.7479 C805.1574,317.5779 811.3199,317.9515 816.0227,323.5927 C819.8738,315.4873 825.4728,316.2472 830.3649,322.5569 C835.4778,316.2666 839.3654,317.5551 842.9303,324.0752 C846.9392,316.7184 853.211,315.8564 859.0442,321.8777 C863.0998,317.0927 868.4942,317.0172 871.3515,323.2199 C874.6091,315.4272 881.2788,314.3936 886.9608,320.4965 C891.2953,314.8373 896.8201,315.4889 899.9203,321.8295 C903.8754,316.1393 910.1015,317.562 912.918,323.1426 C917.5685,317.1126 924.7685,317.2818 928.5642,324.1774 C932.3141,317.5108 936.3498,316.8992 941.4552,322.7855 C946.8232,315.135 954.1255,317.3285 956.7761,325.4287 C960.9292,318.2515 965.0918,317.4604 970.6342,324.0279 C974.8258,318.1521 980.4237,319.9434 982.3412,326.2189 C990.084,328.523 993.3402,332.4456 988.1149,340.1315 C996.066,343.1292 995.9477,348.4513 990.1149,353.5096 C997.2278,355.1334 999.3584,358.6679 995.0563,365.1412 C999.7715,370.144 998.2696,377.1261 991.3948,379.0856 C996.2033,385.2041 995.235,392.8219 986.1351,394.0527 C990.666,398.2893 991.0733,403.0828 984.3221,405.5384 C982.2541,413.8205 974.9515,414.0364 970.118,408.3507 C966.6894,414.2038 960.5565,414.7882 956.4938,409.0992 C953.3744,416.8236 947.5376,416.9745 942.4723,411.1065 C939.0933,419.2426 931.7257,418.9254 926.6304,413.0464 C922.8771,418.3817 918.1533,419.6413 914.0541,413.4229 C909.4096,421.5453 903.5402,420.1962 898.8025,413.5189 C896.2541,420.4163 891.2766,421.7355 885.9435,416.4608 C880.6017,422.292 875.6817,423.6638 871.2087,415.5431 C866.8991,420.9083 860.6333,419.3712 858.0841,413.4888 C854.1124,419.9176 847.5893,418.8992 844.1159,412.9276 C838.4901,418.8163 834.6477,417.3757 830.9149,410.9056 C826.9906,417.5705 820.3328,416.9785 816.8549,410.4306 C811.8895,417.9727 804.544,416.839 801.2681,408.7463 C797.5646,414.0337 791.5576,413.0544 788.9869,407.4671 C781.5578,403.5098 780.514,397.7297 786.6794,391.7736 C780.1051,389.7407 779.6843,383.9186 784.7338,379.9698 C777.6222,376.7943 777.0792,372.2109 781.7727,366.4499 C776.4987,360.1531 777.9257,354.8792 785.8486,352.4149 C778.7046,347.3351 779.1299,343.0854 786.5483,338.7515 C780.8945,333.3761 782.4069,328.5016 789.4788,326.066 " fill="#FFFFFF" filter="url(#fyc6o7633s18l)" style="stroke:#000000;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="195" x="787" y="341.9951">Public DOT Nameservers</text><!--MD5=[42d63f371a1b2b55232c669850b6835e]
+entity Main Thread--><rect fill="#FEFECE" filter="url(#fyc6o7633s18l)" height="46.2969" style="stroke:#A80036;stroke-width:1.5;" width="125" x="247.5" y="199"/><rect fill="#FEFECE" height="10" style="stroke:#A80036;stroke-width:1.5;" width="15" x="352.5" y="204"/><rect fill="#FEFECE" height="2" style="stroke:#A80036;stroke-width:1.5;" width="4" x="350.5" y="206"/><rect fill="#FEFECE" height="2" style="stroke:#A80036;stroke-width:1.5;" width="4" x="350.5" y="210"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="85" x="262.5" y="231.9951">Main Thread</text><!--MD5=[162bad913f27a966d78603a1f88c43c1]
+entity Resolv--><rect fill="#FEFECE" filter="url(#fyc6o7633s18l)" height="46.2969" style="stroke:#A80036;stroke-width:1.5;" width="86" x="535" y="351"/><rect fill="#FEFECE" height="10" style="stroke:#A80036;stroke-width:1.5;" width="15" x="601" y="356"/><rect fill="#FEFECE" height="2" style="stroke:#A80036;stroke-width:1.5;" width="4" x="599" y="358"/><rect fill="#FEFECE" height="2" style="stroke:#A80036;stroke-width:1.5;" width="4" x="599" y="362"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="46" x="550" y="383.9951">Resolv</text><!--MD5=[3a0ff2b2643b72e8f44f95515b106142]
+entity Recon--><rect fill="#FEFECE" filter="url(#fyc6o7633s18l)" height="46.2969" style="stroke:#A80036;stroke-width:1.5;" width="85" x="32.5" y="199"/><rect fill="#FEFECE" height="10" style="stroke:#A80036;stroke-width:1.5;" width="15" x="97.5" y="204"/><rect fill="#FEFECE" height="2" style="stroke:#A80036;stroke-width:1.5;" width="4" x="95.5" y="206"/><rect fill="#FEFECE" height="2" style="stroke:#A80036;stroke-width:1.5;" width="4" x="95.5" y="210"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="45" x="47.5" y="231.9951">Recon</text><!--MD5=[7e52523184f1c3752292ac9e82232dbb]
+entity LBD--><ellipse cx="549" cy="222" fill="#FEFECE" filter="url(#fyc6o7633s18l)" rx="8" ry="8" style="stroke:#A80036;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="28" x="535" y="251.9951">LBD</text><!--MD5=[6aca76539caedc818cba8c9b47739e40]
+entity CNCP--><rect fill="#FEFECE" filter="url(#fyc6o7633s18l)" height="46.2969" style="stroke:#A80036;stroke-width:1.5;" width="79" x="407.5" y="199"/><rect fill="#FEFECE" height="10" style="stroke:#A80036;stroke-width:1.5;" width="15" x="466.5" y="204"/><rect fill="#FEFECE" height="2" style="stroke:#A80036;stroke-width:1.5;" width="4" x="464.5" y="206"/><rect fill="#FEFECE" height="2" style="stroke:#A80036;stroke-width:1.5;" width="4" x="464.5" y="210"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="39" x="422.5" y="231.9951">CNCP</text><!--MD5=[fd9cb3b1ea3e9ece689fdeecdf204087]
+entity htbt_main_ctx--><rect fill="#FEFECE" filter="url(#fyc6o7633s18l)" height="46.2969" style="stroke:#A80036;stroke-width:1.5;" width="104" x="611" y="199"/><rect fill="#FEFECE" height="10" style="stroke:#A80036;stroke-width:1.5;" width="15" x="695" y="204"/><rect fill="#FEFECE" height="2" style="stroke:#A80036;stroke-width:1.5;" width="4" x="693" y="206"/><rect fill="#FEFECE" height="2" style="stroke:#A80036;stroke-width:1.5;" width="4" x="693" y="210"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="64" x="626" y="231.9951">Main CTX</text><!--MD5=[7f924e49bd00f3f976a57574cd3bc1f6]
+entity instance--><rect fill="#FEFECE" filter="url(#fyc6o7633s18l)" height="46.2969" style="stroke:#A80036;stroke-width:1.5;" width="99" x="260.5" y="351"/><rect fill="#FEFECE" height="10" style="stroke:#A80036;stroke-width:1.5;" width="15" x="339.5" y="356"/><rect fill="#FEFECE" height="2" style="stroke:#A80036;stroke-width:1.5;" width="4" x="337.5" y="358"/><rect fill="#FEFECE" height="2" style="stroke:#A80036;stroke-width:1.5;" width="4" x="337.5" y="362"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="59" x="275.5" y="383.9951">instance</text><!--MD5=[ffedf6a9cdd7339fb62ff841799d1be5]
+entity cnc_txt_rec--><rect fill="#FEFECE" filter="url(#fyc6o7633s18l)" height="46.2969" style="stroke:#A80036;stroke-width:1.5;" width="134" x="795" y="351"/><rect fill="#FEFECE" height="10" style="stroke:#A80036;stroke-width:1.5;" width="15" x="909" y="356"/><rect fill="#FEFECE" height="2" style="stroke:#A80036;stroke-width:1.5;" width="4" x="907" y="358"/><rect fill="#FEFECE" height="2" style="stroke:#A80036;stroke-width:1.5;" width="4" x="907" y="362"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="94" x="810" y="383.9951">CNC TXT REC</text><ellipse cx="886.9744" cy="221.8949" fill="#FEFECE" filter="url(#fyc6o7633s18l)" rx="87.4744" ry="19.8949" style="stroke:#A80036;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="136" x="818.9744" y="224.7416">Heartbeat Auth Impl</text><ellipse cx="439.1177" cy="29.1235" fill="#FEFECE" filter="url(#fyc6o7633s18l)" rx="103.6177" ry="23.1235" style="stroke:#A80036;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="172" x="353.1177" y="31.9702">Another Proone Instance</text><ellipse cx="659.8658" cy="28.7732" fill="#FEFECE" filter="url(#fyc6o7633s18l)" rx="81.8658" ry="18.7732" style="stroke:#A80036;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="123" x="597.3805" y="31.9463">Maintenance Tool</text><!--MD5=[667e7cdd0f777c530ea2dba1c08bd7e6]
+entity victim_host--><polygon fill="#FEFECE" filter="url(#fyc6o7633s18l)" points="251.5,510,261.5,500,368.5,500,368.5,536.2969,358.5,546.2969,251.5,546.2969,251.5,510" style="stroke:#000000;stroke-width:1.5;"/><line style="stroke:#000000;stroke-width:1.5;" x1="358.5" x2="368.5" y1="510" y2="500"/><line style="stroke:#000000;stroke-width:1.5;" x1="251.5" x2="358.5" y1="510" y2="510"/><line style="stroke:#000000;stroke-width:1.5;" x1="358.5" x2="358.5" y1="510" y2="546.2969"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="77" x="266.5" y="532.9951">Victim Host</text><!--MD5=[b7e637a441f953ebc24ed8fcb824f79f]
+link CNCP to Resolv--><path d="M469.62,248.9 C493.56,276.31 531.12,319.32 555.15,346.83 " fill="none" id="CNCP-Resolv" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="558.59,350.78,555.694,341.3665,555.3056,347.01,549.6621,346.6216,558.59,350.78" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="466.33,245.13,469.226,254.5435,469.6144,248.9,475.2579,249.2884,466.33,245.13" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="139" x="514" y="296.0669">Queue TXT REC Query</text><!--MD5=[511425dc7163de3665735b7e68d9281b]
+link Recon to Main Thread--><path d="M117.56,222 C152.24,222 201.88,222 242.05,222 " fill="none" id="Recon-to-Main Thread" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="247.4,222,238.4,218,242.4,222,238.4,226,247.4,222" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="93" x="136" y="215.0669">Event Callback</text><!--MD5=[ea78f22d1962f82ee76cb2026da67b81]
+link Main Thread to instance--><path d="M310,245.13 C310,271.83 310,316.71 310,345.58 " fill="none" id="Main Thread-to-instance" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="310,350.78,314,341.78,310,345.78,306,341.78,310,350.78" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="42" x="311" y="296.0669">Spawn</text><!--MD5=[88cfced2f7268004fb8d4acb0a772cb6]
+link htbt_main_ctx to htbt_auth_impl--><path d="M715.24,222 C738.72,222 767.17,222 794.1,222 " fill="none" id="htbt_main_ctx-to-htbt_auth_impl" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="799.11,222,790.11,218,794.11,222,790.11,226,799.11,222" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="48" x="733.25" y="215.0669">SOLICIT</text><!--MD5=[5d75f5d7b42a2ea2002a94bc95486ae0]
+link cnc_txt_rec to Resolv--><path d="M789.69,374 C738.48,374 671.21,374 626.38,374 " fill="none" id="cnc_txt_rec-Resolv" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="621.13,374,630.13,378,626.13,374,630.13,370,621.13,374" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="794.9,374,785.9,370,789.9,374,785.9,378,794.9,374" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="93" x="661.5" y="367.0669">Query TXT REC</text><!--MD5=[21f13ee85425df7d0d44b20dfd58b782]
+link a_prne_i to LBD--><path d="M460.72,51.76 C474.47,66.42 491.89,86.73 504,107 C524.32,141.02 538.89,185.87 545.32,207.79 " fill="none" id="a_prne_i-to-LBD" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="546.78,212.85,548.1345,203.0947,545.397,208.0451,540.4466,205.3076,546.78,212.85" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="30" x="500" y="95.0669">M2M</text><!--MD5=[32a84a1616dbc00c539143c912f55bdc]
+link mttool to LBD--><path d="M641.51,47.56 C626.81,62.31 606.53,84.54 593,107 C572.61,140.84 558.6,185.77 552.48,207.75 " fill="none" id="mttool-to-LBD" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="551.1,212.82,557.329,205.1912,552.4168,207.9965,549.6114,203.0843,551.1,212.82" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="131" x="610" y="95.0669">Maintenance Access</text><!--MD5=[83cdfa74e954ec923cdff4b0977a496e]
+link instance to victim_host--><path d="M310,397.01 C310,423.1 310,466.58 310,494.76 " fill="none" id="instance-to-victim_host" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="310,499.84,314,490.84,310,494.84,306,490.84,310,499.84" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="35" x="311" y="466.0669">Infect</text><!--MD5=[96da60eb07ff64def7a1d9d5675bf6cf]
+@startuml proone
+package "Proone Instance" as prne_i {
+ [Main Thread]
+ component Heartbeat {
+ interface LBD
+ component CNCP
+ component "Main CTX" as htbt_main_ctx
+ }
+ component Resolv
+ component Recon
+ component "BNE Pool" as bne_pool {
+ [instance]
+ }
+
+ [CNCP] <-d-> [Resolv]: Queue TXT REC Query
+ [Recon] -> [Main Thread]: Event Callback
+ [Main Thread] -d-> [instance]: Spawn
+}
+
+cloud "Public DOT Nameservers" {
+ component "CNC TXT REC" as cnc_txt_rec
+}
+
+usecase "Heartbeat Auth Impl" as htbt_auth_impl
+usecase "Another Proone Instance" as a_prne_i
+usecase "Maintenance Tool" as mttool
+node "Victim Host" as victim_host
+
+[htbt_main_ctx] -> [htbt_auth_impl]: SOLICIT
+[cnc_txt_rec] <-> [Resolv]: Query TXT REC
+a_prne_i -d-> (LBD): M2M
+mttool -d-> (LBD): Maintenance Access
+[instance] -d-> victim_host: Infect
+@enduml
+
+PlantUML version 1.2021.7(Sun May 23 20:40:07 AWST 2021)
+(GPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: OpenJDK 64-Bit Server VM
+Default Encoding: UTF-8
+Language: en
+Country: GB
+--></g></svg> \ No newline at end of file
diff --git a/doc/puml/proone-comp.puml b/doc/puml/proone-comp.puml
new file mode 100644
index 0000000..e203429
--- /dev/null
+++ b/doc/puml/proone-comp.puml
@@ -0,0 +1,34 @@
+@startuml proone
+package "Proone Instance" as prne_i {
+ [Main Thread]
+ component Heartbeat {
+ interface LBD
+ component CNCP
+ component "Main CTX" as htbt_main_ctx
+ }
+ component Resolv
+ component Recon
+ component "BNE Pool" as bne_pool {
+ [instance]
+ }
+
+ [CNCP] <-d-> [Resolv]: Queue TXT REC Query
+ [Recon] -> [Main Thread]: Event Callback
+ [Main Thread] -d-> [instance]: Spawn
+}
+
+cloud "Public DOT Nameservers" {
+ component "CNC TXT REC" as cnc_txt_rec
+}
+
+usecase "Heartbeat Auth Impl" as htbt_auth_impl
+usecase "Another Proone Instance" as a_prne_i
+usecase "Maintenance Tool" as mttool
+node "Victim Host" as victim_host
+
+[htbt_main_ctx] -> [htbt_auth_impl]: SOLICIT
+[cnc_txt_rec] <-> [Resolv]: Query TXT REC
+a_prne_i -d-> (LBD): M2M
+mttool -d-> (LBD): Maintenance Access
+[instance] -d-> victim_host: Infect
+@enduml
diff --git a/doc/sws.md b/doc/sws.md
index 0d18151..9c793f2 100644
--- a/doc/sws.md
+++ b/doc/sws.md
@@ -2,7 +2,22 @@
This document is part of **Proone Worm Project**. See [README.md](/README.md)
for overview.
+Copyright (c) 2019-2021 David Timber &lt;mieabby@gmail.com&gt;
+
## Subsystems
+![Subsystem UML Diagram](img/proone.svg)
+
+The subsystems of Proone consist of the heartbeat worker, the recon worker, the
+resolv worker and the bne worker pool. The recon and bne worker pool work
+organically to infect other hosts whilst the heartbeat serves CNC instructions
+and maintenance access.
+
+Proone does not provide any "attack feature"(DDoS). Using the heartbeat
+subsystem, the user may phase this feature in by
+
+* patching Proone and upgrading binary of instances
+* creating a separate program and running it on the hosts
+
### Heartbeat
**Heartbeat** is a subsystem of Proone that consists of a backdoor and CNC
mechanism on infected devices. **The Heartbeat protocol** is a point-to-point or
@@ -10,17 +25,137 @@ a broadcast framing protocol that works over a transport stream such as TCP/IP.
The subsystem is documented separately in [htbt.md](htbt.md).
### Recon
-TODO
+The role of the Recon(RCN) worker is to discover nodes both on the internet and
+the link-local network. The worker instance takes a target network list and a
+blacklist network list as parametres. */src/data/recon.samepl.conf* is the
+sample lists for **proone-recon**, and `PRNE_RCN_T_IPV4`, `PRNE_RCN_BL_IPV4`,
+`PRNE_RCN_T_IPV6` and `PRNE_RCN_BL_IPV6` macro defines are for hardcoded values
+in Proone. The `PRNE_RCN_PORTS` macro defines the target remote remote TCP ports
+the Recon worker sends fabricated SYN packets to. The worker sends fabricated
+SYN packets to randomly generated IP addresses within the target networks.
+
+At least one target network for each version of IP must be specified. You may
+choose to target all networks by specifying 0.0.0.0/0 and ::/0 respectively. For
+efficiency, you may specify the networks for special uses such as 127.0.0.0/8,
+224.0.0.0/4, ::/128, ::1/128, 1::/64 and so on. You may or may not want to
+blacklist private network addresses as devices sitting befine NATed networks.
+Note that the NATed devices still can be controlled by TXT REC CNC. However,
+NAT routers are usually low to mid-range devices so infecting too many devices
+on the private network can put strain on the NAT router.
+
+The SYN packets are sent with the special signatures the worker generates for
+each iteration cycle. When a node responds with a SYN+ACK packet, the worker
+then recognises the signature in the packet and invokes the callback function to
+notify the user of the worker, the Proone main itself. Due to the nature of the
+raw sockets used, the worker receives all the IP packets the host node receives.
+The worker is able to distinguish the relevant packets from other traffic in and
+out of the node with the signatures. The duration of one cycle is set to one
+second plus minus the jitter. This effectively corresponds to the timeout value
+as the worker would not recognise the signature it generated in the previous
+cycle.
+
+The crafted TCP packets sent using raw sockets are not managed by the kernel.
+The kernel is required to send RST packets when it receives any TCP packets that
+it does not recognise. For each SYN+ACK packet received(when the worker finds an
+open port), there will be an RST sent back to the source node.
+
+The Recon worker creates one raw socket for sending raw IP packets and another
+for all the IP packets the host receives for each IP version. 4 sockets in total
+will be created on a host that supports IPv6. Mirai uses only one socket for
+sending and receiving raw packets. The reason Proone uses 4 is due to the
+inconsistency with the `IP_HDRINCL` flag in the API(the Linux kernel does not
+seem to support it for IPv6). Also, a different approach had to be used for
+discovering IPv6 nodes because the address space of IPv6 is large. The only way
+to achieve this is using 2 types of raw sockets for each IP version.
+
+The link-local addresses assigned to the network interfaces by the system are
+used as source addresses for multicasting probe packets to the link-local
+network. In order to inquire these addresses, the platform-specific API
+functions are used as this functionality is not covered by the POSIX. Especially
+for IPv6, scope ids must be queried in order to use link-local addresses.
+
+The Recon worker discovers the IPv6 nodes on the network by multicasting ICMPv6
+ECHO packets with a bogus DSTOPT(0x9e, reserved for private experimentation).
+All nodes on the network are required by the IPv6 spec to send an ICMPv6 packet
+with type 4 and code 2 to notify the source node of the erroneous DSTOPT.
+They're not allowed by the spec to process the ICMPv6 data in the packet The
+Recon worker is capable of processing normal ECHO replies in case bad IPv6
+implementations proceed to process the ICMPv6 part of the packet. Upon receiving
+ICMPv6 4/2, the Recon worker then sends a TCP SYN to confirm that the node has
+any of the targets port open.
+
+References:
+
+* RFC7707
+* RFC4727
+* https://www.iana.org/assignments/ipv6-parameters/ipv6-parameters.xhtml
### BNE
-TODO
+The Break And Enter(BNE) worker, as the name suggests, break-and-enters into the
+target host using vulnerabilities. The basic credential dictionary("combo list")
+based brute force login method is implemented. The interface can be extended so
+that the worker supports other methods using known or zero-day remote code
+execution vulnerabilities.
+
+The worker is also responsible for M2M functions of Proone such as M2M binary
+upgrade if the Heartbeat vector is enabled. With the vector enabled, the Local
+Backdoor port on the target is be tried before actual abusive methods are tried
+for efficiency. If the worker successfully establishes a TLS connection, it
+means that the target host is running Proone(2-way certificate verification and
+ALPN check. See [htbt.md](htbt.md) for more). The worker determines which of the
+hosts should be updated. If the remote host is running an old version, the
+worker will update the executable of the remote instance and vice versa by
+performing binary recombination. This functionality can be disabled by making
+the callback function always return 0.
+
+Unlike the other workers which run as services, the BNE worker is more of a task
+than a worker. The worker exits once the task is carried out - when the breaking
+and entering process was successful, or all the vectors are tried. An instance
+of the BNE worker is spawned whenever a callback is received from the RCN
+worker. Multiple instances of the BNE worker can be run simultaneously(note that
+these threads are not "real". Proone uses GNU Pth to limit its execution to one
+physical thread). The maximum number of BNE workers is set to the arbitrary
+magic number 128(`PROONE_BNE_MAX_CNT`). The chance of an instance reaching this
+limit is rare. On most embedded devices, the process will run out of memory long
+before reaching this limit. After a certain point, further attempts to spawn a
+worker will fail with ENOMEM. Or it is possible that the BNE threads will start
+suffering from starvation. For this reasion, the BNE workers have lowest
+priority to minimise the starvation of other vital workers.
+
+### Resolv
+The Resolv worker is a DNS resolver specifically designed for Proone. It is
+mainly used for TXT REC CNC.
+
+Queries are based on the promise-future model. When a query is successfully
+queued, the caller is given a future object that it can wait on using Pth
+functions. The TCP connections to the name servers are kept open for a certain
+amount of time after a query is processed. When there's a constant flow of
+queries, say when the Heartbeat worker is processing a long stream of TXT
+records, the same name server will be used so long as the server allows. When
+the server returns an error or the connection drops whilst processing a query,
+another hardcoded name server will be randomly selected from the pool in effort
+to continue the process. Multiple servers can be involved for one query(this
+fact becomes relevant when the changes made to the record is propagating among
+the name servers around the world). If there's no internet connection, the
+worker will circle through the name servers until the query times out. A short
+connection timeout value is used to achieve this.
+
+The Resolv worker supports basics only. It is capable of resolving TXT, A and
+AAAA records. It does not depend on any system configuration. Only the harcoded
+DoT public name servers are used and only the hardcoded TLS certificate and
+private key are used to make it difficult to analyze packets exchanged between
+the name servers and the process.
+
+The worker sends the "close notify" SSL alert message when closing the
+connection gracefully. Some DoT servers do not appreciate this and drops the
+connection with RST right away. There is no side effect from this issue.
## Binary Archive and Data Vault
Proone aims to be a decentralised botnet. To spread without binary distribution
servers, Proone carries all the executables of arch types it supports. For this,
a special file structure is designed.
-The **Data Vault**("**DVault**") is a binary block containing large and
+The **Data Vault**("**DVault**") is a binary block that contains large and
sensitive data necessary for operation of Proone. DVault is a kempt version of
the data table of Mirai. DVault also helps reduce the size of Proone. Each
executable contains the *.data* section. If there's a long string in the
@@ -43,13 +178,84 @@ to store exceptionally large values. This issue may be solved by compressing the
value separately at the cost of CPU time.
The **Binary Archive**("**BA**") is a binary block containing compressed
-executables and an index of the executables.
+executables for various operating systems and CPU architectures. The executables
+are compressed into a single stream of data. The executables are indexed by the
+OS codes and arch codes. Each entry of the index is a tuple of the size and
+offset in the uncompressed stream of the executables. A new copy of BA is
+generated each time the instance performs binary recombination for the target
+host.
## Binary Recombination
-TODO
+```
+ linux armv4t host targetting linux sh4
+
+ ┌──────────────┐ ┌──────────────┐
+ │ │ ┌──── decompress ──> │ │
+ │ E L F │ ╵ │ E L F │
+ │ linux armv4t │ ────────────────────────────┐ │ linux sh4 │
+ │ │ │ │ │ │
+ ├──────────────┤ │ │ ├──────────────┤
+ │ DVault │ ───────────────────────────╴│╶───── copy ──> │ DVault │
+ ├──────────────┤ │ │ ├──────────────┤
+ │ BA index │ ───────────────────────────╴│╶─── udpate ──> │ BA index │
+ ├--------------┤ │ │ ├--------------┤
+ │ linux sh4 │ ────────────────────────┘ └── compress ──> │ linux armv4t │
+ │ linux i686 │ ───────────────────────────── recompress ──> │ linux i686 │
+ │ linux mips │ ───────────────────────────── recompress ──> │ linux mips │
+ │ linux mpsl │ ───────────────────────────── recompress ──> │ linux mpsl │
+ │ linux ppc │ ───────────────────────────── recompress ──> │ linux ppc │
+ │ linux m68k │ ───────────────────────────── recompress ──> │ linux m68k │
+ └──────────────┘ └──────────────┘
+```
+
+The Proone executable is a regular ELF file with extra binary data appended to
+it. Proone parses its own executable in order to locate the appended data during
+the initialisation process. Having located the data, Proone then proceeds to
+load the DVault and the binary archive(BA). The offsets to these are kept in
+memory and used to initiate binary recombination later on.
+
+Binary Recombination is a process of preparing the executable for the target
+host after a successful breaking and entering. If the host is of the same
+platform(arch and OS), the executable of the host is simply copied to the target
+host. If the target host is a different platform and the BA contains the
+executable for that platform, a process is initiated for creation of the
+executable for the target host:
+
+* The executable for the target platform is extracted from the archive
+* The DVault is appended to the executable
+* The new BA to be appended is generated - the host executable is compressed
+ with other uncompressed executables in the BA
+
+The diagram above summaries the case when the host platform is linux/armv4t and
+the target platform is linux/sh4. The compressed stream of executable is
+uncompressed and compressed again each time a true binary recombination occurs.
+This is to maximise the entropy and avoid the overhead from having many streams.
+
+Proone supports ELF only. Note that Proone cannot run if it fails to load
+DVault. Being unable to parse the executable is fatal. Should different
+executable formats such as COFF and PE be used, parsing of those formats must be
+implemented.
## IPv6
-TODO: precedence
+Proone is IPv6 ready. The Resolv worker supports IPv6 public DNS over TLS
+servers. The Recon worker supports discovery of IPv6 hosts on the network and
+IPv6 network targets.
+
+Proone always favours IPv6 connectivity. Whenever the instance connects to the
+public DNS over TLS servers or an authoritive heartbeat host, it attempts to
+establish both IPv4 and IPv6 connection. If both connections are established,
+the instance drops the IPv4 connection and uses IPv6 connection. The minor issue
+with this approach is when the IPv6 handshake process takes a little longer than
+that of IPv4. The instance will choose to use the IPv4 connection even though
+the IPv6 handshake would have completed. The reasons for designs are ...
+
+* IPv6 is relatively a new technology. The assumption is that the most network
+ administrators overlook the IPv6 configuration
+* IPv6 offers more load-balancing mechanisms like RA and RH
+* Under the assumption that the connection will the least latency and congestion
+ will finish the handshake process
+* It saves the step of checking connectivity for each IP version(using
+ `getsockname()` or `gethostinfo()`)
## Requirements
### Targetting Wide Range of Devices and Kernel Configurations
@@ -98,7 +304,26 @@ will be single core, anways. The strategy is getting the most small-powered
devices infected rather than having a few infected high-performance systems.
### Ephemeral Presence
-TODO
+Just like Mirai, Proone makes no attempt to seek permanent residency on the
+device. There are many reasons for this. The major one is to make it hard to
+capture the executable from the device. Both Mirai and Proone delete their
+executable as soon as the process starts so that the only way to retrieve the
+executable is through inspecting the file system the executable had been
+uploaded to or making a core dump of the process or the entire system. It is
+difficult to do the latter because it requires development tools and the kernel
+has to support core dumps on the device. Ordinary embedded devices are not
+equipped for this. It would have been impossible to capture the executable of
+Mirai running in the wild.
+
+Proone takes it up a notch and makes it even more difficult. The BNE worker is
+programmed to use only tmpfs and devtmpfs mount points for the upload location
+whereas the Mirai loader, the program responsible for uploading the botnet
+executable to the host, looks for any read-writable mount points. By using only
+memory-backed file systems, Proone eliminates the change of traces of the
+executable being left on non-volatile storage devices. The executable size of
+Proone is quite big since it carries executable for other platforms. On most
+embedded devices, the size of SPI flash memory is small while the RAM is
+reletively spacious. So it would be unwise to use just any mount point.
## Dependencies
The dependencies for Proone have been kept to absolute necessities. libssh2 is
@@ -111,5 +336,143 @@ libyaml and mariadb-connector-c-devel is required to build hostinfod. YAML has
been chosen for the configuration file format and output format of
proone-htbtclient. MariaDB for DB backend.
+## Files and Directories
+### Directories
+* /doc: documentation root directory
+* /doc/puml: PlantUML source files
+* /doc/img: images used in documentation
+* /templates: (undocumented)
+* /src: source root directory
+* /src/data: program data and configuration
+* /src/data/proto: (undocumented)
+* /src/data/sql: SQL files
+* /src/proone_conf.skel: skeleton Proone instance data and configuration header
+* /src/proone_conf: Proone instance data and configuration header for build
+* /.vscode: Visual Studio Code configuration
+* /scripts: main shell scripts
+* /builds: /scripts/build-all.sh script output directory
+* /builds/misc: miscellaneous testing tools for target host arches
+* /builds/tools: tools for build host
+* /builds/proone.bin: Proone instance executables, ELF only
+* /builds/debug: executable debugging symbols
+* /builds/proone: deployable Proone instance executables
+
+### Executables
+* /src/proone: Proone instance executable with DVault only
+* /src/proone.bin: Proone instance executable ELF part only (not runnable)
+* /src/proone-bne: standalone bne tool for testing and index case(P0)
+* /src/proone-hostinfod: hostinfo daemon, an example of authoritive heartbeat
+ implementation
+* /src/proone-htbtclient: heartbeat client, Proone instance maintenance tool
+* /src/proone-htbthost: standalone heartbeat worker for testing
+* /src/proone-ipaddr-arr: tool for converting ip address strings to C arrays
+* /src/proone-list-arch: (undocumented)
+* /src/proone-mkcdict: credential dictionary build tool
+* /src/proone-mkdvault: DVault binary build tool
+* /src/proone-pack: binary archive build tool
+* /src/proone-recon: standalone recon tool for testing
+* /src/proone-resolv: standalone resolv tool for testing
+* /src/proone-rnd: uniform pseudorandom number generator testing tool
+* /src/proone-stress: CPU stress tool (no FPU use)
+* /src/proone-test_bitfield: test suite for variable-length bitfield
+* /src/proone-test_iobuf: test suite for byte vector for input/output buffer
+* /src/proone-test_proto: project protocol test suite
+* /src/proone-test_util: test suite for util functions
+
+### Data and Configuration
+* /src/cred_dict.bin: credential dictionary build output in binary format
+* /src/dvault.bin: DVault binary build output
+* /src/proone_conf/cred_dict.txt: credential dictionary used for build
+* /src/proone_conf.skel/cred_dict.txt: placeholder
+* /src/data/cred_dict.sample.txt: credential dictionary sample
+* /src/data/hostinfod.conf.sample: hostinfo daemon sample configuration
+* /src/data/recon.sample.conf: standalone recon tool sample configuration
+
+### Source
+* /src/bitfield.c: variable-length bitfield
+* /src/bitfield.h: variable-length bitfield
+* /src/bne.c: break and Entering worker
+* /src/bne.h: break and Entering worker
+* /src/config_gen.h: project build configuration (Autoheader)
+* /src/config.h: project environment configuration
+* /src/cred_dict.c: credential dictionary
+* /src/cred_dict.h: credential dictionary
+* /src/data.h: DVault key enum
+* /src/dvault.c: data vault
+* /src/dvault.h: data vault
+* /src/endian.h: host endianness
+* /src/htbt.c: heartbeat worker
+* /src/htbt.h: heartbeat worker
+* /src/imap.c: integer-key ordered binary map
+* /src/imap.h: integer-key ordered binary map
+* /src/inet.c: project-specific internet protocol utils
+* /src/inet.h: project-specific internet protocol utils
+* /src/iobuf.c: byte vector for input/output buffer
+* /src/iobuf.h: byte vector for input/output buffer
+* /src/iset.c: integer set
+* /src/iset.h: integer set
+* /src/libssh2.c: project-specific libssh2 utility functions
+* /src/libssh2.h: project-specific libssh2 utility functions
+* /src/llist.c: linked-list
+* /src/llist.h: linked-list
+* /src/mbedtls.c: project-specific mbedtls utility functions
+* /src/mbedtls.h: project-specific mbedtls utility functions
+* /src/pack.c: packaging facilities for binary archive and nybin
+* /src/pack.h: packaging facilities for binary archive and nybin
+* /src/proone-bne.c: standalone bne
+* /src/proone.c: Proone instance
+* /src/proone.h: Proone instnace
+* /src/proone_conf.skel/config.h: domain-specific configuration
+* /src/proone_conf.skel/x509.h: domain-specific PKI data
+* /src/proone-hostinfod.c: hostinfo daemon
+* /src/proone-htbtclient.c: heartbeat client
+* /src/proone-htbthost.c: standalone heartbeat worker
+* /src/proone-ipaddr-arr.c: tool for converting ip address strings to C arrays
+* /src/proone-list-arch.c: (undocumented)
+* /src/proone-mkcdict.c: credential dictionary build tool
+* /src/proone-mkdvault.c: DVault binary build tool
+* /src/proone-pack.c: binary archive build tool
+* /src/proone-recon.c: standalone recon tool
+* /src/proone-resolv.c: standalone resolv tool
+* /src/proone-rnd.c: uniform pseudorandom number generator testing tool
+* /src/proone-stress.c: CPU stress tool (no FPU use)
+* /src/proone-test_bitfield.c: test suite for variable-length bitfield
+* /src/proone-test_iobuf.c: test suite for byte vector for input/output buffer
+* /src/proone-test_proto.c: project protocol test suite
+* /src/proone-test_util.c: test suite for util functions
+* /src/protocol.c: project protocols including heartbeat
+* /src/protocol.h: project protocols including heartbeat
+* /src/pth.c: project-specific util functions for GNU Portable Threads
+* /src/pth.h: project-specific util functions for GNU Portable Threads
+* /src/recon.c: recon worker
+* /src/recon.h: recon worker
+* /src/resolv.c: resolv worker
+* /src/resolv.h: resolv worker
+* /src/rnd.c: uniform pseudorandom number generator interface
+* /src/rnd.h: uniform pseudorandom number generator interface
+* /src/rnd_well512.c: Well Equidistributed Long-period Linear 512-bit variant
+ pseudorandom number generator implementation
+* /src/strmap.c: string-key ordered binary map
+* /src/strmap.h: string-key ordered binary map
+* /src/util_ct.h: project compile-time utility functions
+* /src/util_rt.c: project runtime utility functions
+* /src/util_rt.h: project runtime utility functions
+
+### Scripts
+* /bootstrap.sh: Autotools set up script
+* /gen-copying.sh: script for generating COPYING in various formats
+* /scripts/build-all.sh: script for building Proone for deployment
+* /scripts/build-arch.sh: script for building one arch target
+* /scripts/do_symsize.sh: (undocumented)
+* /scripts/extsymsize.sh: (undocumented)
+* /src/build-utils.sh: file alignment tool used by Makefile recipe
+* /src/data/proto/print-raw.sh: (undocumented)
+* /src/run-tests.sh: (undocumented)
+* /src/test-resolv.sh: test suite for resolv worker
+* /src/txtrec-del.sh: CNC TXT REC deletion tool
+* /src/txtrec-enc.sh: CNC TXT REC data encoding tool
+* /src/txtrec-set.sh: CNC TXT REC set up tool
+* /src/data/sql/hi-create.sql: MariaDB schema for hostinfo daemon
+## Footnotes
[^1]: i.e. representing values in code: `int value = 123;`