尝试使用 AS3登录到 RDP

我试图登录到 RDP 使用 AS3(空气)。我做得很好,考虑到缺乏资源了解实际的过程。

我已经通过了最初的发送用户名,收到了来自服务器的响应,现在处于初始请求连接。

我正在发送我所有的数据,当嗅探流量时,我看到 netmon 正确地识别我正在发送的数据包类型(t125)。我是 没有被断开的 RDP 和他们发送一个 ack数据包-但我没有收到我期待的回应。

我一直在交叉引用 connectoid,它是一个开源的 RDP 客户端。在连接代码中,我被困在了他们写小整数和大整数混合的地方。

当我查看有限的示例(更像是数据包转储)时,我发现这个过程的连接长度是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;
}
3126 次浏览

显然,缓冲区的大部分是 little endian,但是在其开始的几个字节期望是16位(short)的大 endian 数。这意味着,您必须使用 little endian 编写数据,就好像它会被解释为 big endian 一样。为了将数据从 big endian 转换为 little endian,您可以使用一个将其 endian 设置为 big 的临时 ByteArray,在其中写入数据,然后在主缓冲区数组上调用 writeBytes(),然后清除临时 big endian 数组。编写常量可以手动完成,因为您可以自己改变字节顺序,比如当您使用 big endian 作为 short 来编写 0x0005时,您只需将 0x0500作为 little endian 来编写即可。您似乎使用无关的 dataBuffer编写了代码,并且 endian 是 big,因此您了解这种技术。不过,最好还是在函数中生成一个适当的 dataBuffer。我正在尝试根据我下载的 connectoid代码修改你下面的代码,这样它就会返回一个格式正确的 ByteArray,其中的 endian 很小——这只有当你从它读取有序数据时才有意义,而不是当你读取字节时。

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;
}

希望这个能帮上忙。