Skip to content

Instantly share code, notes, and snippets.

@passthehashbrowns
Created September 9, 2022 17:28
Show Gist options
  • Save passthehashbrowns/a6f46856219ef353be2e49bf323f173d to your computer and use it in GitHub Desktop.
Save passthehashbrowns/a6f46856219ef353be2e49bf323f173d to your computer and use it in GitHub Desktop.
This is a reimplementation of the bof_pack function in Aggressor.
#Custom function to pack our arguments for BOFs
#Usage: Call it the same way you would call bof_pack
sub custom_pack {
local('$beaconId $formatString $formatStringFixed @argsFixed $totalSize $shiftCounter $index $binarySize $packedData')
#We don't really need this but keeping it so the calling convention is the same
$beaconId = $1;
#Our original format string
$formatString = $2;
#Format string placeholder since we need to modify the values
$formatStringFixed = '';
#Drop the beacon ID and format string from our args, so that we just have the args to be packed
#We could add a flatten call here if we wanted to pass in an array in the args too
@argsFixed = sublist(@_, 2);
#Calculate our total size, which gets packed at the end
$totalSize = 0;
#Whenever we add an item to the list we need to keep track of that to keep referencing the correct index
$shiftCounter = 0;
#Iterate through our format string and access the relevant data to be packed
for ($index = 0; $index < strlen($formatString); $index++){
#If we have an int
if((charAt($formatString, $index) cmp "i") == 0){
$totalSize += 4;
$formatStringFixed = $formatStringFixed . 'i';
}
#If we have a short
if((charAt($formatString, $index) cmp "s") == 0){
$totalSize += 2;
$formatStringFixed = $formatStringFixed . 's';
}
#If we have binary data
if((charAt($formatString, $index) cmp "b") == 0){
$binarySize = strlen(@argsFixed[$index + $shiftCounter]);
$totalSize += $binarySize; #Size of our binary data
#We need to pack the size of the data ahead of the data
$formatStringFixed = $formatStringFixed . 'i';
add(@argsFixed, $binarySize, $index + $shiftCounter);
$shiftCounter++;
#Z indicates that we'll specify how many bytes to read
$formatStringFixed = $formatStringFixed . 'Z' . $binarySize;
}
#If we have a normal string
if((charAt($formatString, $index) cmp "z") == 0){
$totalSize += strlen(@argsFixed[$index + $shiftCounter]) + 1; #Size of the string + a null terminator
#We need to pack the size of the string ahead of the actual string
$formatStringFixed = $formatStringFixed . 'i';
add(@argsFixed, strlen(@argsFixed[$index + $shiftCounter]) + 1, $index + $shiftCounter);
$shiftCounter++;
#z is read characters until null byte
$formatStringFixed = $formatStringFixed . 'z';
}
#If we have a wide string
if((charAt($formatString, $index) cmp "Z") == 0){
$totalSize += strlen(@argsFixed[$index + $shiftCounter]) * 2 + 2; #Size of the string + a null terminator (2 since it's UTF-16)
#We need to pack the size of the string ahead of the actual string
$formatStringFixed = $formatStringFixed . 'i';
add(@argsFixed, strlen(@argsFixed[$index + $shiftCounter]) * 2 + 2, $index + $shiftCounter);
$shiftCounter++;
#u is read UTF-16 characters until null byte, and it needs to be little endian
$formatStringFixed = $formatStringFixed . 'u-';
}
}
#Add our total size to the args
push(@argsFixed, $totalSize);
#Add our size int to the format string
$formatStringFixed = $formatStringFixed . "i";
#Need to reverse this, just how pack works I guess
@argsFixed = reverse(@argsFixed);
#Pack our data
$packedData = pack($formatStringFixed, @argsFixed);
#Not really sure why but we need to trim off the last 4
$packedData = substr($packedData, 0, strlen($packedData) - 4);
return $packedData;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment