กำลังพยายามเข้าสู่ระบบ RDP โดยใช้ AS3


147

ฉันพยายามที่จะเข้าสู่ระบบ RDP โดยใช้ AS3 (อากาศ) ฉันตกลงแล้วโดยพิจารณาว่าไม่มีทรัพยากรเพียงพอที่จะเข้าใจกระบวนการจริง

ฉันได้รับชื่อผู้ใช้เริ่มต้นที่ผ่านมาได้รับการตอบกลับจากเซิร์ฟเวอร์และตอนนี้ฉันอยู่ที่การเชื่อมต่อคำขอเริ่มต้น

ฉันกำลังส่งข้อมูลทั้งหมดของฉันและเมื่อสูดข้อมูลจราจรฉันเห็นว่า netmon รับรู้อย่างถูกต้องว่าฉันกำลังส่งแพ็คเก็ตประเภทใด (t125) ฉันไม่ได้ถูกตัดการเชื่อมต่อโดย RDP และพวกเขาส่งackแพ็คเก็ต - แต่ฉันไม่ได้รับการตอบสนองที่ฉันคาดหวัง

ฉันได้อ้างอิงข้ามconnectoidซึ่งเป็นไคลเอนต์ RDP โอเพนซอร์ส ในรหัสการเชื่อมต่อฉันติดที่พวกเขาเขียนส่วนผสมของจำนวนเต็มเล็กน้อยและใหญ่ endian

เมื่อฉันดูตัวอย่างที่ จำกัด ที่นั่น (เช่นทิ้งแพ็กเก็ต) ฉันเห็นว่าความยาวการเชื่อมต่อสำหรับกระบวนการนี้คือ 412 แต่ของฉันbytearrayก็เหมือนกับ 470

ฉันเปลี่ยนconnectoidวิธีการเป็นสิ่งที่ฉันเชื่อว่าถูกต้อง แต่ด้วยการผสมผสานของประเภท endian ฉันก็ยังไม่แน่ใจ

ฉันขอโทษถ้าสิ่งนี้อ่านไม่ออก แต่ฉันพยายามทำให้ดีที่สุดเพื่อช่วยคุณ ฉันจะแนบรหัสที่แสดงสิ่งที่ฉันได้พยายามทำในการแปลง

public function sendMcsData(): void {
    trace("Secure.sendMcsData");
    var num_channels: int = 2;
    //RdpPacket_Localised dataBuffer = new RdpPacket_Localised(512);
    var hostlen: int = 2 * "myhostaddress.ath.cx".length;
    if (hostlen > 30) {
        hostlen = 30;
    }
    var length: int = 158;
    length += 76 + 12 + 4;
    length += num_channels * 12 + 8;
    dataBuffer.writeShort(5); /* unknown */
    dataBuffer.writeShort(0x14);
    dataBuffer.writeByte(0x7c); //set 8 is write byte //write short is setbigendian 16 //
    dataBuffer.writeShort(1);
    dataBuffer.writeShort(length | 0x8000); // remaining length
    dataBuffer.writeShort(8); // length?
    dataBuffer.writeShort(16);
    dataBuffer.writeByte(0);
    var b1: ByteArray = new ByteArray();
    b1.endian = Endian.LITTLE_ENDIAN;
    b1.writeShort(0xc001);
    dataBuffer.writeBytes(b1);
    dataBuffer.writeByte(0);
    var b2: ByteArray = new ByteArray();
    b2.endian = Endian.LITTLE_ENDIAN;
    b2.writeInt(0x61637544);
    dataBuffer.writeBytes(b2);
    //dataBuffer.setLittleEndian32(0x61637544); // "Duca" ?!
    dataBuffer.writeShort(length - 14 | 0x8000); // remaining length
    var b3: ByteArray = new ByteArray();
    b3.endian = Endian.LITTLE_ENDIAN;
    // Client information
    b3.writeShort(SEC_TAG_CLI_INFO);
    b3.writeShort(true ? 212 : 136); // length
    b3.writeShort(true ? 4 : 1);
    b3.writeShort(8);
    b3.writeShort(600);
    b3.writeShort(1024);
    b3.writeShort(0xca01);
    b3.writeShort(0xaa03);
    b3.writeInt(0x809); //should be option.keybaortd layout just guessed 1
    b3.writeInt(true ? 2600 : 419); // or 0ece
    dataBuffer.writeBytes(b3);
    // // client
    // build? we
    // are 2600
    // compatible
    // :-)
    /* Unicode name of client, padded to 32 bytes */
    dataBuffer.writeMultiByte("myhost.ath.cx".toLocaleUpperCase(), "ISO");
    dataBuffer.position = dataBuffer.position + (30 - "myhost.ath.cx".toLocaleUpperCase()
        .length);
    var b4: ByteArray = new ByteArray();
    b4.endian = Endian.LITTLE_ENDIAN;
    b4.writeInt(4);
    b4.writeInt(0);
    b4.writeInt(12);
    dataBuffer.writeBytes(b4);
    dataBuffer.position = dataBuffer.position + 64; /* reserved? 4 + 12 doublewords */
    var b5: ByteArray = new ByteArray();
    b5.endian = Endian.LITTLE_ENDIAN;
    b5.writeShort(0xca01); // out_uint16_le(s, 0xca01);
    b5.writeShort(true ? 1 : 0);
    if (true) //Options.use_rdp5)
    {
        b5.writeInt(0); // out_uint32(s, 0);
        b5.writeByte(24); // out_uint8(s, g_server_bpp);
        b5.writeShort(0x0700); // out_uint16_le(s, 0x0700);
        b5.writeByte(0); // out_uint8(s, 0);
        b5.writeInt(1); // out_uint32_le(s, 1);
        b5.position = b5.position + 64;
        b5.writeShort(SEC_TAG_CLI_4); // out_uint16_le(s,
        // SEC_TAG_CLI_4);
        b5.writeShort(12); // out_uint16_le(s, 12);
        b5.writeInt(false ? 0xb : 0xd); // out_uint32_le(s,
        // g_console_session
        // ?
        // 0xb
        // :
        // 9);
        b5.writeInt(0); // out_uint32(s, 0);
    }
    // Client encryption settings //
    b5.writeShort(SEC_TAG_CLI_CRYPT);
    b5.writeShort(true ? 12 : 8); // length
    // if(Options.use_rdp5) dataBuffer.setLittleEndian32(Options.encryption ?
    // 0x1b : 0); // 128-bit encryption supported
    // else
    b5.writeInt(true ? (false ? 0xb : 0x3) : 0);
    if (true) b5.writeInt(0); // unknown
    if (true && (num_channels > 0)) {
        trace(("num_channels is " + num_channels));
        b5.writeShort(SEC_TAG_CLI_CHANNELS); // out_uint16_le(s,
        // SEC_TAG_CLI_CHANNELS);
        b5.writeShort(num_channels * 12 + 8); // out_uint16_le(s,
        // g_num_channels
        // * 12
        // + 8);
        // //
        // length
        b5.writeInt(num_channels); // out_uint32_le(s,
        // g_num_channels);
        // // number of
        // virtual
        // channels
        dataBuffer.writeBytes(b5);
        trace("b5 is bigendin" + (b5.endian == Endian.BIG_ENDIAN));
        for (var i: int = 0; i < num_channels; i++) {
            dataBuffer.writeMultiByte("testtes" + i, "ascii"); //, 8); // out_uint8a(s,
            // g_channels[i].name,
            // 8);
            dataBuffer.writeInt(0x40000000); // out_uint32_be(s,
            // g_channels[i].flags);
        }
    }
    //socket.
    //buffer.markEnd();
    //return buffer;
}

3
คุณสามารถดักจับแพ็กเก็ตที่ละเมิดจากไคลเอนต์ RDP ที่รู้จักดีและเปรียบเทียบกับแพ็คเก็ตที่คุณอยากรู้ได้หรือไม่? อาจเป็นข้อผิดพลาดในวิธีที่คุณเข้ารหัสส่วนของอาร์เรย์ไบต์
Ben

คุณช่วยอธิบายเกี่ยวกับสิ่งที่คุณหมายถึงได้ที่ "การเชื่อมต่อคำขอเริ่มต้น" ได้ไหม คำขอเริ่มต้นควรได้รับการส่งผ่านแล้วเพื่อให้คุณเข้าสู่ระบบดังนั้นจึงไม่ชัดเจนว่าสถานะของคุณติดอยู่ที่ใด คุณได้ส่งคำขอการเชื่อมต่อของคุณ (0xe0) และได้รับการยืนยันของคุณ (0xd0) และตอนนี้คุณอยู่ในเฟส "เชื่อมต่อเริ่มต้น" แล้วหรือยัง หรือที่ไหนสักแห่งต่อไปตามลำดับเหตุการณ์? แพ็กเก็ตที่คุณสร้างในโค้ดด้านบนเป็นแพ็กเก็ต "MCS: connect-initial" หรือไม่
Max Worg

2
คำถามงี่เง่า แต่คุณได้ลอง RDP ด้วยตนเองลงในช่องนั้นเพื่อดูว่ามันใช้งานได้? อาจมีบางอย่างเกิดขึ้นเพื่อป้องกันการลงชื่อเข้าใช้เช่นแบนเนอร์ "เครื่องนี้มีไว้สำหรับการใช้งานที่ได้รับอนุญาตเท่านั้น blah blah"
Cryptographic_ICE

ไม่ทราบว่าคุณได้ทำสิ่งนี้ไปแล้ว แต่คุณควรดูซอร์สโค้ดของ KRDC ( ลิงก์ ) หรือ freerdp ( ลิงก์ ) พวกเขาอาจให้ข้อมูลเชิงลึกเกี่ยวกับปัญหาของคุณ
Nadeem Douba

ดูเหมือนว่าจากซอร์สโค้ดของ connectoid ข้อมูลในแพ็กเก็ตเหล่านี้จะถูกเข้ารหัสด้วย BER คุณควรเขียนฟังก์ชั่นสองสามตัวเพื่อให้ง่ายขึ้นจากการสร้างข้อมูลแพ็คเก็ตด้วยตนเองและเพื่อช่วยในการดีบักโค้ดของคุณ (และของเรา)
Alex Mazzariol

คำตอบ:


4

เห็นได้ชัดว่าส่วนใหญ่ของบัฟเฟอร์เป็น endian น้อย แต่หลายไบต์ที่จุดเริ่มต้นของมันคาดว่าจะเป็นตัวเลข endian ใหญ่ 16 บิต (สั้น) ซึ่งหมายความว่าคุณต้องเขียนข้อมูลใน endian น้อยราวกับว่ามันจะถูกตีความว่าเป็น endian ใหญ่ ในการแปลงข้อมูลจาก endian ใหญ่เป็น endian น้อยคุณสามารถใช้ชั่วคราวByteArrayที่มี endian ที่ตั้งไว้เป็นใหญ่เขียนข้อมูลแล้วเรียกใช้writeBytes()array buffer หลักของคุณแล้วล้างอาร์เรย์ endian ใหญ่ชั่วคราว ค่าคงที่การเขียนสามารถทำได้ด้วยตนเองเนื่องจากคุณสามารถเลื่อนคำสั่งไบต์ได้ด้วยตัวเองพูดว่าเมื่อคุณเขียน0x0005เป็น endian ตัวใหญ่ให้สั้นคุณก็แค่เขียน0x0500endian ตัวน้อยแทน คุณดูเหมือนจะเขียนรหัสด้วยสิ่งที่ไม่เกี่ยวข้องdataBufferด้วย endian ที่มีขนาดใหญ่คุณจึงรู้เทคนิคนี้ ยังดีกว่าที่คุณจะสร้างที่เหมาะสมdataBufferในฟังก์ชั่น ฉันกำลังพยายามแก้ไขรหัสของคุณด้านล่างโดยยึดตามconnectoidรหัสที่ฉันดาวน์โหลดมาเพื่อที่ว่ามันจะกลับมามีรูปแบบที่ถูกต้องเมื่อByteArrayEndian ยังมีน้อย - เรื่องนี้จะเกิดขึ้นก็ต่อเมื่อคุณอ่านข้อมูลที่สั่งจากมันไม่ใช่เมื่อคุณอ่านไบต์

public function sendMcsData(): ByteArray {
    trace("Secure.sendMcsData");
    var num_channels: int = 2;
    var dataBuffer:ByteArray=new ByteArray(); //RdpPacket_Localised dataBuffer = new RdpPacket_Localised(512);
    // it's better to build the data buffer in the function, as in java, otherwise you can receive interference
    dataBuffer.endian=Endian.LITTLE_ENDIAN; // for clarity
    var hostlen: int = 2 * "myhost.ath.cx".length; // hardcoded? TODO FIX
    if (hostlen > 30) {
        hostlen = 30;
    }
    var length: int = 158;
    length += 76 + 12 + 4; // Options.use_rdp5 is true, apparently
    length += num_channels * 12 + 8;
    dataBuffer.writeShort(0x0500); // writing big-endian 0x5 *unknown*
    dataBuffer.writeShort(0x1400); // writing big-endian 0x14
    dataBuffer.writeByte(0x7c); //set 8 is write byte 
    //write short is setbigendian 16 //
    dataBuffer.writeShort(0x0100); // writing big-endian 0x01
    var be:ByteArray=new ByteArray();
    be.endian=Endian.BIG_ENDIAN; // create big-endian array for the data that's not static
    be.writeShort(length | 0x8000); // remaining length
    dataBuffer.writeBytes(be);
    be.clear(); // so that extra writing will not spoil the array
    dataBuffer.writeShort(0x0800); // writing big-endian 0x08 (length?)
    dataBuffer.writeShort(0x1000); // writing big-endian 16 (0x10)
    dataBuffer.writeByte(0);
    dataBuffer.writeShort(0xc001); // this one is little endian by default
    dataBuffer.writeByte(0);
    dataBuffer.writeUnsignedInt(0x61637544);
    //dataBuffer.setLittleEndian32(0x61637544); // "Duca" ?!
    be.writeShort((length - 14) | 0x8000); // remaining length
    dataBuffer.writeBytes(be);
    be.clear();
    dataBuffer.writeShort(SEC_TAG_CLI_INFO);
    dataBuffer.writeShort(212); // length
    dataBuffer.writeShort(4);
    dataBuffer.writeShort(8);
    dataBuffer.writeShort(600); // Options.width
    dataBuffer.writeShort(1024); // Options.height
    dataBuffer.writeShort(0xca01);
    dataBuffer.writeShort(0xaa03);
    dataBuffer.writeInt(0x0409); //Options.keylayout, default English/US - fixed
    dataBuffer.writeInt(2600); // or 0ece
    dataBuffer.writeBytes(b3);
    // // client
    // build? we
    // are 2600
    // compatible
    // :-)
    /* Unicode name of client, padded to 32 bytes */
    var targetPos:int=dataBuffer.position+32; // to account for padding
    dataBuffer.writeMultiByte("myhost.ath.cx".toLocaleUpperCase(), "UTF-16"); 
    // buffer.outUnicodeString(Options.hostname.toUpperCase(), hostlen);
    // apparently encoding is used "Unicode" that is UTF-16. If that will not work, set UTF-8 here
    // and by all means check what is on the wire when you connect via conventional RDP

    dataBuffer.position = targetPos;
    // this seems to be your mistake in converting position truncate, 
    // as position after writing already accounts for the writing been processed.
    // This line alone can be the source of size discrepancy you observe.
    dataBuffer.writeInt(4);
    dataBuffer.writeInt(0);
    dataBuffer.writeInt(12);
    dataBuffer.position = dataBuffer.position + 64; // /* reserved? 4 + 12 doublewords */
    // note, if the position wouldn't shift forward, write zeroes manually
    dataBuffer.writeShort(0xca01); // out_uint16_le(s, 0xca01);
    dataBuffer.writeShort(1);
    if (true) //Options.use_rdp5)
    {
        dataBuffer.writeInt(0); // out_uint32(s, 0);
        dataBuffer.writeByte(24); // out_uint8(s, g_server_bpp);
        dataBuffer.writeShort(0x0700); // out_uint16_le(s, 0x0700);
        dataBuffer.writeByte(0); // out_uint8(s, 0);
        dataBuffer.writeInt(1); // out_uint32_le(s, 1);
        dataBuffer.position = dataBuffer.position + 64;
        dataBuffer.writeShort(SEC_TAG_CLI_4); // out_uint16_le(s,
        // SEC_TAG_CLI_4);
        dataBuffer.writeShort(12); // out_uint16_le(s, 12);
        dataBuffer.writeInt(0xd); // out_uint32_le(s,
        // g_console_session
        // ?
        // 0xb
        // :
        // 9);
        // the comments say 9, but the code says 0xd - leaving 0xd in place
        // Options.console_session is hardcoded false
        dataBuffer.writeInt(0); // out_uint32(s, 0);
    }
    // Client encryption settings //
    dataBuffer.writeShort(SEC_TAG_CLI_CRYPT);
    dataBuffer.writeShort(12); // length
    // if(Options.use_rdp5) dataBuffer.setLittleEndian32(Options.encryption ?
    // 0x1b : 0); // 128-bit encryption supported
    // else
    dataBuffer.writeInt(true ? (false ? 0xb : 0x3) : 0);
    dataBuffer.writeInt(0); // unknown
    if (true && (num_channels > 0)) {
        trace(("num_channels is", num_channels));
        dataBuffer.writeShort(SEC_TAG_CLI_CHANNELS); // out_uint16_le(s,
        // SEC_TAG_CLI_CHANNELS);
        dataBuffer.writeShort(num_channels * 12 + 8); // out_uint16_le(s,
        // g_num_channels
        // * 12
        // + 8);
        // //
        // length
        dataBuffer.writeInt(num_channels); // out_uint32_le(s,
        // g_num_channels);
        // // number of
        // virtual
        // channels
        for (var i: int = 0; i < num_channels; i++) {
            targetPos=dataBuffer.position+8; // account for padding/truncation
            dataBuffer.writeMultiByte("testtes" + i, "ascii"); //, 8); // out_uint8a(s,
            // g_channels[i].name,
            // 8);
            dataBuffer.position=targetPos;
            dataBuffer.writeInt(0x00000040); // out_uint32_be(s,
            // g_channels[i].flags);
            // writing big-endian 0x40000000
        }
    }
    trace("sendMCSData: Data buffer length is",dataBuffer.length); // debug
    return dataBuffer;
}

หวังว่านี่จะช่วยได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.