Porting code using sizeof() from C++ to PHP - php

I have some C++ code (segment seen below), I need to convert this to another language (namely PHP). The code, as seen, uses structs, which PHP doesn't do. I know I can "kind of" emulate structs through objects/arrays, however, this isn't the same. That is not my main problem though. I need a way to implement the sizeof() function found in C++ (since PHP's sizeof() function just counts the number of elements in an array/object).
typedef unsigned long Offset;
typedef unsigned long Size;
struct Location {
Offset offset;
Size size;
};
struct Header {
unsigned long magic;
unsigned long version;
struct Location elements;
struct Location ids;
struct Location strings;
struct Location integers;
struct Location decimals;
struct Location files;
};
int Build() {
Header theheader;
theheader.magic = *((unsigned long*)"P3TF");
theheader.version = 272;
theheader.elements.offset = sizeof(theheader);
theheader.elements.size = element_offset;
theheader.ids.offset = ((theheader.elements.offset + theheader.elements.size + 15) / 16) * 16;
theheader.ids.size = ids_offset;
theheader.strings.offset = ((theheader.ids.offset + theheader.ids.size + 15) / 16) * 16;
theheader.strings.size = string_offset;
theheader.integers.offset = ((theheader.strings.offset + theheader.strings.size + 15) / 16) * 16;
theheader.integers.size = 0;
theheader.decimals.offset = ((theheader.integers.offset + theheader.integers.size + 15) / 16) * 16;
theheader.decimals.size = 0;
theheader.files.offset = ((theheader.decimals.offset + theheader.decimals.size + 15) / 16) * 16;
theheader.files.size = file_offset;
theheader.padding[0] = 0;
theheader.padding[1] = 0;
fwrite(&theheader, 1, sizeof(theheader), file_handle);
}
Can anyone please point me in the right direction on how to do this?
Any help would be appreciated.

Obviously recreating sizeof from C will be a difficult feat, as C is statically-typed and, traditionally, sizeof is evaluated at run-time by the compiler. PHP is also pretty quiet about its memory usage.
One method of dynamically grabbing the size of an object is to use memory_get_usage (official PHP reference) before and after the allocation of the object in question. Of course, you'll run into some fun calculations when you compare the two memory usage values, as storing the values into variables will allocate memory also.
This is a pretty shaky method of recreating sizeof, but if it works it works.

You could simply sum all sizes of the objects in the array or object. However, that still only gets the length of strings, etc. If you want the actual size of the binary representation of the object, you'll have to do some additional math, such as converting all ints to 32 bits (or 64) and appending a null byte to all UTF-8 strings. If you're using charsets, do make sure that they are single-byte or at least measurable in bytes.
PHP does not have a function that checks the memory size of an object.

Related

How to conver bin data to int16 in php

I have this code in Qt c++
const unsigned char *packed = reinterpret_cast<const unsigned char*>(data.constData());
res.type = static_cast<int>(packed[0]);
res.period = static_cast<int>(packed[1]);
res.rate = static_cast<qint16>(packed[2] | (packed[3] << 8)) / 100.;
res.edge = static_cast<qint16>(packed[4] | (packed[5] << 8)) / 100.;
return res;
How to convert it from c++ to php
I try this:
$a = unpack ("C*", $data);
$eventList = [];
for ($i=0; $i < $a[1]; $i++)
{
$event = array ();
$index = $i * 6 + 2;
$event["type"] = $a[$index];
$event["period"] = $a[$index+1];
$event["rate"] = ($a[$index+2] | ($a[$index+3] << 8)) / 100;
$event["edge"] = ($a[$index+4] | ($a[$index+5] << 8)) / 100;
}
Edge conver wrong
Very big value.
[edge] => 650.86
must be -4.5
Type, period and rate is good;
Help me please
Don't know the exact answer but some of possible ways to solve the problem:
Check $a[$index+4] and $a[$index+5] value by using var_dump to get its value and type:
var_dump($a[$index+4]);
var_dump($a[$index+5]);
is the data type and its value as expected? Probably good idea is to check as above all data before/after calculation to exactly know what you are dealing with.
Double check your conversion type, perhaps you should't use C* but other, perhaps S or s?
conversion types
If you need type conversion in php you can check how it is done here: Type Juggling and Casting
Note that in PHP you can use a string with ASCII digit that can be treated as digit for calculations:
$foo = 5 * "10 Little Piggies"; // $foo is integer (50)
Which is something you probably don't want.
If you expect negative value but you get positive you have problem because your'e not setting MSB by shifting bits:
The MSB can also correspond to the sign bit of a signed binary number
read-wiki
in case packed[5] should be negative but it isn't
If this not helps then provide data sample and expected values for Edge, Type, period and rate.

Was there a a time when PHP's rand() function was used as an exploit?

Does anybody know if there was a time or event where somebody used rand()'s weakness in order to predict exploit it? Something like generating tokens or cheating in video games?
Since prior to PHP 7, rand() was very easy to crack. In fact here is some C code, credit to Peter Selinger, that predicts the values given a seed:
#include <stdio.h>
#define MAX 1000
#define seed 1
main() {
int r[MAX];
int i;
r[0] = seed;
for (i=1; i<31; i++) {
r[i] = (16807LL * r[i-1]) % 2147483647;
if (r[i] < 0) {
r[i] += 2147483647;
}
}
for (i=31; i<34; i++) {
r[i] = r[i-31];
}
for (i=34; i<344; i++) {
r[i] = r[i-31] + r[i-3];
}
for (i=344; i<MAX; i++) {
r[i] = r[i-31] + r[i-3];
printf("%d\n", ((unsigned int)r[i]) >> 1);
}
}
So once again, was there a time when this weakness was used in order to predict the next random number and exploit something?
Thanks!
Before PHP 7, PHP use Linear Congruential Generator algorithm to generate a random number or in short LCG. The algorithm works as follow:
next_random = (previous_random * a + c) % m
previous_random = next_random
When you first make a random, obviously, there is no previous_random number. That's why we provide seed. So, seed is just a first previous_random value.
Now, we know the algorithm, but we need to know what the value of a, c, and m that PHP use. I believe that each version of PHP use different value for those. But let say we do not know those value, how do we guess this value. In my case, I am using PHP 5.6.15 Windows.
srand(0);
var_dump(rand()); // 12345
var_dump(rand()); // 5758
So, m = getrandmax () + 1. Since our seed is 0, so our c = 12345. To get value a, we can use simple loop to guess a.
$m = getrandmax () + 1;
for($a = 0; $a < $m; $a++)
if ((($a * 12345 + 12345) % $m) == 5758)
var_dump($a); // in my case, 20077
or you can get value a like this
srand(0); rand(); // 12345
srand(1); rand(); // 32422
// so a = 32422 - 12345 = 20077
Now, I am able to write the same random function as my current PHP version.
class visal_rnd
{
function __construct($seed = 0) {
$this->seed = $seed;
}
function rnd() {
$this->seed = ($this->seed * 20077 + 12345) % 32768;
return $this->seed;
}
}
However
I was able to predict my own PHP version because I have so much knowledge about my current environment, I know a few previous random, I know the seed. If the attacker has almost zero knowledge, it would not be easy to attack.
Mersenne Twister
PHP 7.0+, by default, use Mersenne Twister. There are more parameters to be guessed than Linear Congruential Generator. So, it requires more knowledge.
Is Linear Congruential Generator Bad?
Depends on how much information you have exposed to the public. If you generate only one random number and attacker has no knowledge of a, previous_random, c and m. It is impossible for attackers to predict the next random number.

PHP: Signed Binary Strings

I'm having a problem with converting binary strings to signed integers
If you call decbin('-40'), php will output 1111111111111111111111111111111111111111111111111111111111011000
But if you call bindec(decbin('-40')), it will output 1.84467440737E+19 (or something similar, which is obviously not -40) because it "sees the most significant bit as another order of magnitude rather than as the sign bit" - php manual
Is there a way to convert a binary 64 bit binary string (much like the one output by decbin) string into a signed integer?
From the documentation, you cannot use bindec
bindec() interprets all binary_string values as unsigned integers. This is because bindec() sees the most significant bit as another order of magnitude rather than as the sign bit.
base_convert appears to ignore signing altogether.
If you know that your incoming string will always be 64 bit binary and you are not on a 32 bit system, it's quite easy to write a custom function.
Check if the string is 64 characters long.
Check if the most significant bit is a 1.
Flip all bits
Add 1
Negate
Here's a quick one I knocked together.
function bindec2($bin)
{
if (strlen($bin) == 64 && $bin[0] == '1') {
for ($i = 0; $i < 64; $i++) {
$bin[$i] = $bin[$i] == '1' ? '0' : '1';
}
return (bindec($bin) + 1) * -1;
}
return bindec($bin);
}
Use pack and unpack to convert between int and binary string.
// 'i' means signed integer
var_dump(unpack('i', pack('i', '-40'))); // gives you -40

First position of true value(1) from a bit pattern

For example, if the pattern is as follows:
bit [10010][1011][1000]
position 54321 4321 4321
result 2 1 4
I want to get the result from right to left position as [2] [1] [4]
If I understand your question correctly, you are looking for a function that returns the index of the least significant 1-bit in an integer. If so, check whether your platform implements the function ffs() ("find first set"). On Linux, you can do man ffs to get the full documentation. On other programming platforms the function may be named differently, e.g. in NVIDIA's CUDA, it exists as a device function __ffs().
Assuming the bit pattern is represented by an int you could do something like
if(bitPattern == 0) {
return 0;
}
int count = 1;
while(bitPattern % 2 == 0) {
bitPattern >>= 1;
count++;
}
return count;
$n = log($x & (~$x+1))/log(2)
~x + 1 is exact the same as -x, as the result of the 2's complement. So why would you use the more complex and slower?
And there are many bithacks to quickly find integer log2x instead of using the much more slower floating point log as above. No slowly divide is needed too. Since x & -x yields only the last bit which is a power of 2, you can use the following function to get log2
unsigned int log2p2(unsigned int v) // 32-bit value to find the log2 of v
{
static const unsigned int b[] = {0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0,
0xFF00FF00, 0xFFFF0000};
register unsigned int r = (v & b[0]) != 0;
for (i = 4; i > 0; i--) // unroll for speed...
{
r |= ((v & b[i]) != 0) << i;
}
}
There are many other ways to calculate log2x which you can find here
So your code is now simply
log2p2(x & -x);

Why is the number 16 converted to float(6.1026988574311E_320) by PHP using Zend_Amf

The Zend_Amf specification states that a Number type returned from flash will map to a float in PHP. Fine. But why does the number 16 get returned as 6.1026988574311E_320 ? PHP version is 5.2.9 running on OS X.
I have tried forcing a cast to integer in PHP (the above value gets rounded to 0) and also from Actionscript using int(16) - the latter comes through as NULL. How can ensure that Flash returns an integer via AMF and that PHP can deal with it?
You have a classic endian problem. Looks like either Zend or flash is doing the wrong thing with the endianness of this double. Here is the a program that prints the double (and its hex value). It then reverses the endianness and prints it again.
#include <stdio.h>
#include <stdint.h>
int main(void)
{
double d = 16;
uint32_t *i = (uint32_t *)(&d);
uint8_t *c = (uint8_t *)(&d);
size_t j;
printf("%08x %08x %lg\n", i[1], i[0], d);
for(j = 0; j < sizeof(double) / 2; j++)
{
uint8_t tmp;
tmp = c[j];
c[j] = c[sizeof(double) - j - 1];
c[sizeof(double) - j - 1] = tmp;
}
printf("%08x %08x %lg\n", i[1], i[0], d);
return 0;
}
On an Intel (little endian processor), you get this output
40300000 00000000 16
00000000 00003040 6.1027e-320
Are you perhaps running this on a PPC Mac (big endian)? Seems like one of your tools is not doing the right thing on your architecture. File a bug with the vendors.
As a hacky workaround, I suggest turning your number into a string and then converting it back to a double on the other end.
I don't know entirely what is going wrong in your situation, but I think I may be able to partially illuminate what is happening to your code. I ran the following quick hack to test a theory:
void hexdump_double(double dbl)
{
assert(8 == sizeof(dbl));
printf("double: %02X %02X %02X %02X %02X %02X %02X %02X (%lg)\n",
((char *)&(dbl))[0],
((char *)&(dbl))[1],
((char *)&(dbl))[2],
((char *)&(dbl))[3],
((char *)&(dbl))[4],
((char *)&(dbl))[5],
((char *)&(dbl))[6],
((char *)&(dbl))[7],
dbl);
}
int main()
{
hexdump_double(6.1026988574311E-320);
}
Which produces some exciting output:
double: 40 30 00 00 00 00 00 00 (6.1027e-320)
As you can see, that little floating-point number isn't any random pattern of bits. However, it also doesn't look to be related to "16."
Where Zend_Amf documentation states that ActionScript Number type is returned as a PHP float, what is meant is the class Number documented by Adobe: Adobe.com Flex documentation. It does not mean that any "number" will be passed as a double.
An int with value less than 2^29 will be returned transmitted in AMF as an integer type, and I assume Zend_Amf will return this as an integer.
How are you transmitting the AMF object from your ActionScript? Is it feasible to dump the bytes being sent?

Categories