Search This Blog

Saturday, May 17, 2008

PDU Format Extraction

Peace be upon you,

How are you guys? I hope that all of you is Ok, today I am going to show you peace of code that I really like, this code actually doing a very nice thing, which is extracting the characters from the SMS, what I mean here if you have any knowledge about SMS, you will now that it sent in 7 bits format called "PDU" Protocol Data Unit, the extraction of this data is not tough, but I just demonstrating the beauty of the bit wise operation and how it minimize the code size, here is the first peace of code, it suppose to extract the PDU data and make it readable ASCII characters data.

Function Name : PDUChunk
Author : Ahmed Essam
Date : 17 - 05 - 2008
Purpose : Convert 7 bytes of PDU data to 8 bytes of Char data

History Revision
17-05-2008 Created AEssam
char* PDUChunk(char* Source)
// it is just constant to the block size
int nBase = 8 ;
// Allocate 9 bytes because of the nature of null terminated sting
char *cpResult = new char[9];
// Clean the allocated memory

// in each loop we keep part of the byte for the next byte, this the variable
// which will hold the rest of the opreation to the next character
unsigned char cRest = 0;
// in Each loop the mask changes, because the shifting that happen from using 7 bits from 8 bits
char cMask = 128;
for(int nLoop=0;nLoop<=nBase;nLoop++)
// shifting the current set of bits to the appropriate location,
// and put the rest the we keep from last byte at the end of the current bits set
cpResult[nLoop] = ((Source[nLoop] & ~cMask)<< (nLoop%nBase)) (cRest>>(nBase-(nLoop%nBase)));
// keep the unused set of bits to the next opreation
cRest = Source[nLoop] & cMask;
// update the mask for the next usage
cMask = cMask >> 1;

Function Name : PDUChunk
Author : Ahmed Essam
Date : 17 - 05 - 2008
Purpose : Convert PDU data to of Char data
History Revision
17-05-2008 Created AEssam
char* FromPDU2Char(char* Source,int len)
// Loops counter to end the loop by the end of the data retrieval
int nLoops = 0;
// This to calculate the CHAR length, after extracting it from PDU
// This is faster to avoid using floating point, if we are using floating point it will be (len/7) * 8)
int nTotalLen = (((len*10)/7) * 8)/10;
// Allocate memory for the end char array
char *cpResult = new char[nTotalLen];
// Clean the memory up
// Extract the Char from the PDU
char *cpChunk = PDUChunk(Source + nLoops);
// Safe concatenation for the end result
// Delte the return char array
delete []cpChunk;
// Add the chunck size to the loop counter
// Examining the loops count against the length of the PDU data
while (nLoops<len);
// Return the result string

Here is the code that consume that code

char cpSourceMSG[] = "\xc1\x60\x30\x18\x0c\x06\x83\xc1\x60\x30\x18\x0c\x06\x83\xc1\x60\x30\x18\x0c\x06\x83\xc1\x60\x30\x18\x0c\x06\x83\xc1\x60\x30\x18\x0c\x06\x83\xc1\x60\x30\x18\x0c\x06\x83\xc1\x60\x30\x18\x0c\x06\x83\xc1\x60\x30\x18\x0c\x06\x83\xc1\x60\x30\x18\x0c\x06\x83\xc1\x60\x30\x18\x0c\x06\x83\xc1\x60\x30\x18\x0c\x06\x83\xc1\x60\x30\x18\x0c\x06\x83\xc1\x60\x30\x18\x0c\x06\x83\xc1\x60\x30\x18\x0c\x06\x83\xc1\x60\x30\x18\x0c\x06\x83\xc1\x60\x30\x18\x0c\x06\x83\xc1\x60\x30\x18\x0c\x06\x83\xc1\x60\x30\x18\x0c\x06\x83\xc1\x60\x30\x18\x0c\x06\x83\xc1\x60\x30\x18\x0c\x06\x83";

// Extract the characters from the pSourceMSG
char * cpExtractedMSG = FromPDU2Char(cpSourceMSG,sizeof(cpSourceMSG));

this message suppose to be a SMS full of "A", which means 160 character of A, the function up there is not 100% safe but it is working OK for now,

in the function "PDUChunk", you will notice there is line full of bit wise operations

that is the line I am talking about

cpResult[nLoop] = ((Source[nLoop] & ~cMask)<< (nLoop%nBase)) (cRest>>(nBase-(nLoop%nBase)));

this line should do all the targeted purpose, it suppose to get the latest shifting value and apply it on the current value of PDU, then do ORING with the remain value from the last operation, I know that you may not understand what I am talking about, here is link that explains that issue in details

anyways, the coming part is nice, the coming part is we are going to extract the Unicode SMS, actually it doesn't need any effort, it just little endian and we are going to make it big endian

char cpUnicodeMSG[] = "\x06\x33\x06\x2a\x06\x2a\x06\x35\x06\x44\x00\x20\x06\x28\x06\x43\x06\x45\x00\x20\x06\x45\x06\x48\x06\x28\x06\x4a\x06\x46\x06\x4a\x06\x44\x00\x20\x06\x44\x06\x25\x06\x33\x06\x2a\x06\x43\x06\x45\x06\x27\x06\x44\x00\x20\x06\x28\x06\x4a\x06\x27\x06\x46\x06\x27\x06\x2a\x06\x43\x06\x45\x00\x20\x06\x48\x06\x41\x06\x42\x06\x27\x06\x4b\x00\x20\x06\x44\x06\x2a\x06\x39\x06\x44\x06\x4a\x06\x45\x06\x27\x06\x2a\x00\x20\x06\x2c\x06\x47\x06\x27\x06\x32\x00\x20\x06\x27\x06\x44\x06\x25\x06\x2a\x06\x35\x06\x27\x06\x44\x06\x27\x06\x2a";
char *cpFlippedArray = new char[sizeof(cpUnicodeMSG)];
for(int n=0;n<sizeof(cpUnicodeMSG)/2;n++)
cpFlippedArray[n*2] = cpUnicodeMSG[(n*2)+1] ;
cpFlippedArray[(n*2)+1] = cpUnicodeMSG[n*2] ;
TCHAR *wsUnicodeString = (TCHAR*)cpFlippedArray ;

it suppose that you will have the result string the wsUnicodeString, after that you are free to do what ever you want to with this string.

Most of you will say, that you see the string in normal Wide Character if you are developing something for MAPI, like MAPI Rule, actually the idea here is little low level, I got this data from the RIL, Radio Interface Layer, I did small application that sniff GSM, and keep everything, this how I got this RAW data, here it is all about the memory and data format in the memory, it is really nice to play with the bit wise stuff :D, I hope that you like the post.

At the end I hope that this post was useful and helpful.

Thanks for your time.

Ahmed Essam

Discover the new Windows Vista Learn more!

No comments: