Packet Tokenizer: 016C (extractor problem)

Forum closed. All further discussion to be discussed at https://github.com/OpenKore/

Moderators: Moderators, Developers

Message
Author
Technology
Super Moderators
Super Moderators
Posts: 801
Joined: 06 May 2008, 12:47
Noob?: No

Packet Tokenizer: 016C (extractor problem)

#1 Post by Technology »

the problem:
packet extraction with JCV's RO tools returns this in the recvpackets.txt:

Code: Select all

0169 3
016A 43
016A 30
016A 10
016A 30
016A 43
016A 10
016D 14
Motivus wrote:If 016C is not in recvpackets.txt manually add it as length 43, or else you will receive random disconnects

I haven't checked if JCV's properly checks for that type, but I highly doubt it because it is the first packet that looks like that in the length function. Putting how to fix it here for now, will actually fix it later. It's the same as others, but the packet id is identified differently

BE 6C 01 00 00

It will look like this in most disassemblers:
mov esi, 0x16C

Or like this in the one JCV uses (I think):
mov esi, 16C
the dissasembly by olly:
016B (len: A = 10)

Code: Select all

575941	MOV DWORD PTR [EBP-10],16A
575948	CALL 57AFA0
57594D	LEA ECX,[EBP-10]
575950	MOV ESI,16B
575955	PUSH ECX
575956	MOV DWORD PTR [EAX],1E
57595C	MOV ECX,81B320
575961	MOV DWORD PTR [EBP-10],ESI
575964	CALL 57AFA0
575969	LEA EDX,[EBP-10]
57596C	MOV DWORD PTR [EAX],A
575972	PUSH EDX
575973	MOV ECX,81B320
016C (len: 2B = 43)

Code: Select all

575AB0	MOV DWORD PTR [EBP-10],16A
575AB7	CALL 57AFA0
575ABC	MOV DWORD PTR [EAX],1E
575AC2	LEA EAX,[EBP-10]
575AC5	PUSH EAX
575AC6	MOV ECX,81B320
575ACB	MOV DWORD PTR [EBP-10],ESI
575ACE	CALL 57AFA0
575AD3	LEA ECX,[EBP-10]
575AD6	MOV ESI,16C
575ADB	PUSH ECX
575ADC	MOV DWORD PTR [EAX],A
575AE2	MOV ECX,81B320
575AE7	MOV DWORD PTR [EBP-10],ESI
575AEA	CALL 57AFA0
575AEF	LEA EDX,[EBP-10]
575AF2	MOV DWORD PTR [EAX],2B
575AF8	PUSH EDX
575AF9	MOV ECX,81B320
575AFE	MOV DWORD PTR [EBP-10],ESI
575B01	CALL 57AFA0
575B06	MOV DWORD PTR [EAX],2B
575B0C	LEA EAX,[EBP-10]
575B0F	PUSH EAX
575B10	MOV ECX,81B320
575B15	MOV DWORD PTR [EBP-10],16D
575B1C	CALL 57AFA0
575B21	LEA ECX,[EBP-10]
575B24	MOV DWORD PTR [EAX],E
575B2A	PUSH ECX
575B2B	MOV ECX,81B320
Maybe we can solve it like this:
we look for string "MOV ESI," and store the string after the comma (ex. 16C)
when we then encounter a line that starts with: "MOV DWORD PTR [EBP" that has "ESI" after the comma,
we use the value that was put in ESI as the switch
when we then encounter a line that starts with: "MOV DWORD PTR [EAX"
we store the value after the comma as the length (ex. 2B)

here's the modified perl extract-packets.pl:

Code: Select all

#!/usr/bin/env perl
# extract-packets.pl by VCL
# Modified a little bit by SnT2k and Rasqual
# Modified to use with W32DSM by Karasu (code commented out; they conflict with the original code)
#
# This was the old packet extractor script, but now it isn't used anymore.
# It's still kept around for archival purposes.

use strict;
use warnings;

my $LINES_BACK_SEARCH_COUNT = 100;

if (@ARGV < 2) {
	print STDERR "No input file given. Usage: extract-packets.pl <ASM> <OUTPUT> [ADDRESS]\n" .
		"  ASM: the disassembled output of ragexe.exe, as generated\n" .
		"       by 'objdump -d -M intel'\n" .
		"  OUTPUT: the filename of the output file to write to.\n" .
		"  ADDRESS: the address of the packet size function. If not given, this program\n" .
		"           will attempt to auto-detect it.\n";
	exit(1);
}

if (!open (F, "< $ARGV[0]")) {
	print STDERR "Unable to open $ARGV[0]\n";
	exit(1);
}

my $addr;

if (!$ARGV[2]) {
	# Look for the address of the function that determines packet sizes.
	my ($found, $lastLine);
	while ((my $line = <F>)) {
		if ($line =~ /mov    ecx, dword( ptr )?\[ebp-0C\]/ && $lastLine =~ /E8ED0[0-9]0000/) {
			($found) = $lastLine =~ /^:([A-Z0-9]{8})/;
			($addr) = $lastLine =~ /call ([A-Z0-9]+)/;
			last;
		}
		$lastLine = $line;
	}

	if (!defined($addr)) {
		print STDERR "Address of packet size function not found, trying alternate method.\n";
		my ($matched_187) = 0;
		my ($line_counter) = 0;
		seek(F, 0, 0);
		while (<F>) {
			($line_counter)++;
			# mov dword[ebp-08], 00000187
			if (/mov    DWORD PTR \[ebp-8\],0x187$/ ) {
				($found) = $_ =~ /^  ([a-z0-9]{6}):/;
				($matched_187) = 1;
				last;
			}
		}
		if (($matched_187) == 1) {
			# try to find function prologue in LINES_BACK_SEARCH_COUNT previous lines
			$line_counter -= $LINES_BACK_SEARCH_COUNT;
			seek(F, 0, 0);
			while (<F>) {
				($line_counter)--;
				if (($line_counter) <= 0) {
					if (/push   ebp$/ ) {
						($addr) = $_ =~ /^  ([a-z0-9]{6}):/;
					}
				}
				if (($line_counter) == -$LINES_BACK_SEARCH_COUNT) {
					last;
				}
			}
		}
		if (!defined($addr)) {
			print STDERR "Address of packet size function not found using alternate method.\n";
			close(F);
			exit(1);
		}
	}


	print STDERR "Packet size function: $addr (found at $found)\n";
} else {
	$addr = $ARGV[2];
}
print STDERR "Extracting function at $addr...\n";

# Go to that address and get the content of the entire function
our @function;
seek(F, 0, 0);
while ((my $line = <F>)) {
	my $stop = 0;
	if ($line =~ /^  $addr:/) {
		while (($line = <F>)) {
			$line =~ s/[\r\n]//sg;
			if ($line =~ /ret /) {
				$stop = 1;
				last;
			}
			push(@function, $line);
		}
	}
	last if ($stop);
}
close(F);

if (@function == 0) {
	print STDERR "Unable to extract packet size function.\n";
	exit (1);
}


# Extract packets
my (%packets, $ebx, $switch);
print STDERR "Extracting packets...\n";

for (my $i = 0; $i < @function; $i++) {
	$_ = $function[$i];
	# We're only interested in 'mov dword' commands
	# mov dword\[(.*?)\], (.*?)
	if (/mov    DWORD PTR \[(.*?)\],(.*?)$/) {
		my $to = $1;
		my $from = $2;

		if ($to =~ /ebp/ && $from =~ /^0x/) {
			# Packet switch
			$switch = sprintf("%04X", hex($from));

		} elsif ($to =~ /eax/) {
			# Packet length
			my $len;
			if ($from eq 'ebx') {
				$len = $ebx;
			} elsif ($from =~ /^0x/) {
				$len = hex($from);
			} else {
				$len = 0;
			}
			$packets{$switch} = $len;
		}

	} elsif (/mov    ebx,(.*?)$/) {
		$ebx = hex($1);
	} elsif (/mov    esi,(.*?)$/) {
		$switch = sprintf("%04X", hex($1));
	}
}

open(F, "> $ARGV[1]");
foreach my $key (sort keys %packets) {
	print F "$key $packets{$key}\n";
}
close(F);
print STDERR "Done.\n";
(seems to work on 2010-01-26aRagexeRE.exe for me)

and some other stuff:

the strings we look for to find the packetlen function (the first switch in the function):

Code: Select all

"MOV DWORD PTR [EBP-C],187"
"MOV DWORD PTR [EBP-8],187"
"MOV DWORD PTR [EBP-8],64",
"MOV DWORD PTR [EBP-C],64",
(note: its not always safe to search for something we are not looking for, as we might actually find something!)

storageKey:

Code: Select all

41B38B	MOV DWORD PTR [EBP-30],50B6F79
41B392	TEST AL,AL
41B394	MOV DWORD PTR [EBP-2C],202C179
41B39B	MOV DWORD PTR [EBP-28],E20120
41B3A2	MOV DWORD PTR [EBP-24],4FA43E3
41B3A9	MOV DWORD PTR [EBP-20],179B6C8
41B3B0	MOV DWORD PTR [EBP-1C],5973DF2
41B3B7	MOV DWORD PTR [EBP-18],7D8D6B
41B3BE	MOV DWORD PTR [EBP-14],8CB9ED9
storageEncryptKey 0x050B6F79, 0x0202C179, 0x0E20120, 0x04FA43E3, 0x0179B6C8, 0x05973DF2, 0x07D8D6B, 0x08CB9ED9
One ST0 to rule them all? One PE viewer to find them!
One ST_kRO to bring them all and in the darkness bind them...

Mount Doom awaits us, fellowship of OpenKore!

Locked