Search code examples
c#bittorrenttorrentkademliabencoding

receiving unreadable text while trying to bencode a "find_node" query


Im using the bencodeNET trying to send a find_node query and receive an answer using a bootstrapping node. it seems like the request works well and I do get a response on wireshark and c#. the problem is when decoding (using bencoding ofc) I get unreadable and unusable dictionary code:

IPAddress[] ipAddresses = Dns.GetHostAddresses("router.bittorrent.com");
var endpoint = new IPEndPoint(ipAddresses[0], 6881);

// Create a new bencoded dictionary for the query
BDictionary query = new BDictionary();
query["t"] = new BString("aa"); // transaction ID
query["y"] = new BString("q"); // query type
query["q"] = new BString("find_node"); // query name
// Add additional parameters to the query
BDictionary argsDict = new BDictionary();
argsDict["id"] = new BString(id); // target node ID
Console.WriteLine(BMethods.BytesToId(Encoding.ASCII.GetBytes(argsDict["id"].ToString())) + "penis");
argsDict["target"] = new BString(id); // target ID
query["a"] = argsDict;

Console.WriteLine(argsDict.Get<BString>("id")+"here");
var parser = new BencodeParser(Encoding.GetEncoding("ISO-8859-1"));
// Encode the query as a byte array
var queryBytes = query.EncodeAsBytes();
// Create a new socket

UdpClient udpServer = new UdpClient(11000);

udpServer.Send(queryBytes, queryBytes.Length, endpoint); // reply back
var data = udpServer.Receive(ref endpoint); // listen on port 11000
Console.WriteLine(Encoding.GetEncoding("ISO-8859-1").GetString(data));
BDictionary response = parser.Parse<BDictionary>(data);
foreach (KeyValuePair<BString, IBObject> i in response)
{
    if(i.Value is BDictionary)
    {
        BDictionary b = (BDictionary)i.Value;
        foreach (KeyValuePair<BString, IBObject> j in b)
        {

            Console.WriteLine(j.Key + ": " + BMethods.BytesToId(BMethods.ConvertHexToByte((((BString)j.Value).ToString()))));

        }
        continue;
    }
    Console.WriteLine(i.Key + ": " + ((i.Value).ToString()));
}

id is a random 20 byte array if you're wondering the response output usually looks something like this:

ip: ?Z?w*o id: 2oNisQÿJì)Iº«òûaF|Ag nodes: I??"2/IªLO!d?å?Y3?/lYA??cwIov0ahrth_EqU½?G??▌Ä?÷0ï%(I¼A?ÿ?¡9I?òµ??°O0?~x,B?ªO];'?UDz½??cUP¿}ïWLx?;K=&o¼âC}ÑWAº3{àO\AOé81Ñ B-F¥)ú21?c_ìvyêo?AMe6lcp\g?èöUÉ°_6OrEu[?)??']km?èU¡(á t: aa y: r

with obviously id and nodes being completely unreadable and unusable.

anyone wondering how a proper response should look like its in BEP 5

now with id I could get around this by just taking the bytes and turning the bytes to hex. the problem is the nodes key which holds a lot more information than just a sha-1 id (that being ip and port).

Edit: forgot to add sometimes the response dictionary doesn't contain a "nodes" key at all despite Wireshark showing it should


Solution

  • I don't have the code with me right now but I'll add it later. Essentially "nodes" key as written in bep 5 is composed of 20 bytes of the id, 4 bytes of the IP, and 2 bytes of the port. Using this information you can use this mess of a dump and composed it into a byte array which you can turn into a list of nodes with the information above