I have a small c program which connect and authenticate with my security DVR which in turn starts sending me data over the socket. I can connect on port 5000 or port 80 sending different authentification methods to start receiving the video/images. My problem is; I am new to c first of all, and I am very lost on how to process the data received over the socket. This is the data I am sending to authenticate.
char authenticate[] = {
0x31, 0x31, 0x31, 0x31, 0x88, 0x00, 0x00, 0x00,
0x01, 0x01, 0x00, 0x00, 0x88, 0x7d, 0xa6, 0x47,
0x0c, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x61, 0x64, 0x6d, 0x69, 0x6e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x31, 0x32, 0x33, 0x34,
0x35, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x43, 0x6f, 0x6c, 0x74, 0x6f, 0x6e, 0x73, 0x2d,
0x4d, 0x61, 0x63, 0x42, 0x6f, 0x6f, 0x6b, 0x2d,
0x50, 0x72, 0x6f, 0x2e, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x00, 0x00, 0x00, 0x35, 0x34, 0x32, 0x36,
0x39, 0x36, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00
};
x = sendto(sockfd, authenticate, sizeof(authenticate), 0,
(struct sockaddr*)&servaddr, sizeof(servaddr));
I am then recieving the data with
while(1)
{
n = recvfrom(sockfd, data, 2048, 0, NULL, NULL);
When I connect via http port 80 This is the image data that I receive:
Content-length: 2153
Content-type: image/jpeg
ˇÿˇ‡JFIFHHˇ€Cˇ€Cˇ¿#ˇƒ
ˇƒ8 2A!$X"#3QRTqëîóò“’÷ˇƒˇƒ#
!1A"2QRqrë#SacÅ°¢≥—“ÒBCstÇí¥”ˇ⁄ ?e›n◊}mÀ⁄ÔÅ≥j¿ò[0ÂáֱNU…9'*‚®#ô &yéïùr‰Ù®{ï“däŒÆl$Kkë R,√fƒSl—EX
z \û£≠âflüÈ‚≠ê*àÉ*—1E;q}Ìp6#>øÆÂòŸR≠^Ì˝çò ı;R∆b¡»ü>aÊ∫a˙5KKüz∑¶Î´D“≤κl∂ÎÓ„∆Àn∫¥•sh8vß4≠äöûñy‰H¢çyºí0TQrÏ#π dÅèåfi*XY*F¨Óƒl™¢‰˝S^sgh]î…flzXNü‡†2∑ñæ5t€Tp`qìåos◊iGùjˆ˙+FÈ™‚‘_§≈[”Jˇ *•<*´∆≥ÁpVGfl
ï¶ñ—€{ñgíJmd*ôï„å[YT-J†∞π∂¯ë…{¶dyÓaÓhå©!øg⁄∆™≤È:
≥Ô`Mú)∞ÚÌǯhˇÿ„Tø∑,9˛õ°˛ıØö~ø«ûÔ˝˙aa{ÜÔû÷Èé‡ÂΩk÷ºµ\sÉÒ¬XÓ∞`¯⁄X“">eäÅœ»G¡ìöÜ"˘mütòÅtuÓbÌh;vB1dflL ∂)
´È
Hm∂Í
Ω¡î*Ä≤e‘nÄï‘HΩ…77ÙIè6%â%ãµ"T¿n¢Í3%‹zj#™:”ÂmR˛=L ZsZ[_ïz±»r…™2®ú.«]∑$q¢1)ùftÙ˘îà[q£°Îü&%Ï÷#á∂¿ôEy!ËÇJ0‚‚j»¥|∆fi–ü5"èRj›D˘„õUäú≥û>•«bdôãq]Ö$2ˆ„Gc#,ó±Ò<√-p}ZÍSÛ £ëóŒsäóNçı≠◊òÊö•mÈÇ_W„Y2∆∫9œxπŸ¸*±’dË⁄1(¸05{üfW∆Éû
‘ÿSÑ‘„û.JTÓ9˙Ìø˝∆º=∆ ¬ï∆h≥!`uˆ’Uçõèd„Ï…ı®*GÕıŸ6iíÆiñ¶’ØmBë‰WáÈö˛â‚ı∞>Ó˛◊_Â’ˇπ?º”˘øh~8TÔÕ/ùˆO¬Ewü^◊]…6
ÕïÊ«p2ˆ◊ä”õU÷ËÖˆ◊䲲ãk–«_2ûk4Éÿ‰aÖƒîP∑ùg⁄†·¢µ’ÂS÷}XNï¯5GWæßGk”óS8fòˇ;˝âp;≈“ƒ5ˇ˜„Éû·&Áa¨ö2tÿ±íÉìcÇeÓ"¬Â„(8¯:øØíM £rmfiá~≠æ(:oT/U≤/täó U√ñT0ëªÕ ê’¢víRT#˙‚ìO7ÖÆÒ‘D<dm#;F®—yÑmPǃ5É+FZÀ"8≥-˙7"ç–ãm{Å∑Öunü»à·®icëcoDìf¬·ñ)!å A¡ñÂNrx√aeP\ZM®£ ‘Y\<kJÿ‚’Ó#„Œª+â3
¨π©%Uü±Àñ¨œò§S2àŸßUJjwûYãZ#Ç∆˚¶&hr⁄xj¬ì È™sàK-… 28Fm‡Ôr√û 8Qè
ª∑ØP ptt£‚N—Œ∆Iπ ıo«Y{Èe.U[´‰•ı∫ÎæöÙU’‘…)¶Gy
†“ä]ãä6U≤Å∞b 7X„ ™˙#ÓMÖ∑>_ó
=fiÔ>·π∂ˇ÷ãÎΩfl«Y!µÎô≥—ß;¨J™èΩ|tLoîRˇM›.#nŸÍ±≈±Ê∏Ï~qkãsv≈Xõ‰í∞Lπ/cR,j*6.Sí„ÿ˘fÑ»7f|_™≥RçÿíE°°bã {{Ïõç#·Ãæ:7çú√´u o
⁄N¨Ω\€ù◊K,Z4àÕ8N\˙πÍë’D∫vbfl∏¢>äz.¸¨⁄Ä‘°dx≈ªàˆÕ45‡ßõub-ü%TVTN8⁄∞¨≤µÁñÜD[;o—˘ƒNˇóóØ[ò;´¡O*∫¿ƒ©∏2ߘG#20˘H∆µªú’2€∂O°Â⁄Ùb®äÌ/hÿQÁXÓŸJzB¬Öw]Ù2ÿ—⁄§∆«gÜö·´˚Ëãt‚+˛Iì¯∂⁄nÎ{ºVʬ)aà∆´°ÀÚËÃkr÷â„ç^1©ôæ
óv'ô8∆ãπkB˙цπ¯zÉsÀpv;Ã]ÓI€[Ìj/˙A≤øÒ}O˚ËS|Dûƒˇ¶3=ÓÍæ6?Ú…å!¥›¨Ûˆ¸f…€·I~à≥ g>∆®‰√Û0≥30®Æ) èMÖçGÃ∑dÑÖ∞¥Œéf≥ÔyµE¢Yå.õ·ç+r˙ú ≤ZÄP ‰y¨Km⁄±~ävfl¡'I+b»Ñî[ö<¬ æñ8raEãk
I am unsure if this data is some weird encoding or if it need to be processed somehow to make it valid. I have searched around with no luck or examples of how to properly do this. If i connect via the data port (port 5000 which sends via instead of an image) the data looks pretty much the same although i know it may be processed or unprocessed H.246 video data.
The raw data is an image. It starts after the blank line which terminate the headers.
Code:
n = recvfrom(sockfd, data, 2048, 0, NULL, NULL); // might as well replace with read().
// use a much larger buffer, ideally large enough to fit largest possible whole image
headers_end_str = "\r\n\r\n";
headers_end_position = strstr(data, headers_end_str);
headers_end_position += strlen(headers_end_str );
if (headers_end_position > n) { ... } // handle errors
FILE* fh = fopen("image.jpg", "wb");
int result = fwrite( &( data[ headers_end_position ), n - headers_end_position, 1, fh);
// check result for errors
// continue reading from socket and writing to file, subsequent reads do not have headers
This should get you started, you need to fine tune reading additional data, and also error handling and end of file.
However, even before you have done all that, you should be able to run "file -s image.jpg" (on linux, or cygwin) and it will tell you it's a JPEG image.
I used WireShark to monitor the communication between the DVR and it's web browser plugin client and the authentication message header is similar to your post (0x31 0x31 0x31 0x31...). How did you construct this array? I searched a lot for this protocol documentation but I didn't find.
In my case I do the requests at port 7171 (it's a DVR settings). I also used a while(true) to keep listening this port and the server sends me a h264 stream.
The problem is that the stream is not like rtps protocol describes, see this great post. In our case we have to parse a kind of proprietary header first (that starts with 0x31 0x31 0x31 0x31) to stract the frame, sps and pps.
Related
I have a char *data that is a Datagram to represent the packet I want to send in but I need to insert on that an uint8_t array.
// Datagram to represent the packet
char datagram[4096], source_ip[32], *data, *pseudogram;
// zero out the packet buffer
memset(datagram, 0, 4096);
// IP header
struct iphdr *iph = (struct iphdr *)datagram;
// UDP header
struct udphdr *udph = (struct udphdr *)(datagram + sizeof(struct ip));
// Data part
data = datagram + sizeof(struct iphdr) + sizeof(struct udphdr);
uint8_t packet_bytes[] = { 0xff, 0xff, 0x81, 0x01, 0x01 };
memcpy(data, packet_bytes, 5);
Doing this allows me to insert what I need and it works but the problem is that I have and uint8_t array with 0x00 in the middle making this harder than I thought because the 0x00 hex also means a termination of an array, how can I make it to work with this array instead ?
char packet_bytes[] = {
0xff, 0xff, 0x81, 0x00, 0x00, 0x00, 0x00, 0x30,
0x13, 0x43, 0x00, 0x01, 0x01, 0x01, 0x02, 0x00,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x06, 0x00, 0x00, 0x10, 0x01, 0x01, 0x00, 0x63,
0x02, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x05,
0x00, 0x00, 0x00, 0x0c, 0x00, 0x09, 0x04, 0x00,
0x0a, 0x00, 0x03, 0x01, 0x00, 0x11, 0x77, 0x25
};
the problem is that I have and uint8_t array with 0x00 in the middle making this harder than I thought because the 0x00 hex also means a termination of an array
There is no such thing as "termination of an array" in C. There is null termination of character arrays used as strings, but that isn't applicable here. So the memcpy part will work just fine.
You have some other problems however:
char datagram[4096], char packet_bytes[] etc
char is unsuitable, dangerous and non-portable for the purpose of holding raw binary data. Use uint8_t instead. See Is char signed or unsigned by default?
struct iphdr *iph = (struct iphdr *)datagram;
This will lead to undefined behavior because of alignment and strict aliasing. What is the strict aliasing rule? You cannot wildly type pun from a character array to another type by pointer casts (though the other way around from "any type" to character type is possible). Furthermore, your struct may contain padding, in which case it is extra non-portable and you don't want to be sending padding bytes around.
(struct udphdr *)(datagram + sizeof(struct ip)); Same problem as above.
The only reliable way to do this is either to disable struct padding and then memcpy in/out of the struct. Or alternatively write serialization/deserialization routines accessing one struct member at a time, moving it to/from the raw data.
it seems this code make my display go crazy sometimes (but only sometimes). But when I remove dat=~dat; it seems to work fine.
why?
what I am trying to do here is just make the ascii letters be the oposite: so for example:
11001000 will be:
00110111
or
10101111 would be:
01010000
the reason for doing this is that i want to have one row (the active row) in the diplay window with black on white pixels instead of opostie like the rest of the display window.
Is there some other way I could do this? (invert the numbers)
FYI: I am programing in C. Atmel studio. atmega 4809, SSD1305z display, SPI-simular interface.
void displayinvertedString(char str[], uint8_t ypos,uint8_t xpos)
{
Set_Page_Address(ypos);
Set_Column_Address(xpos);
int len = strlen(str);
uint8_t dat;
int temp;
for (int e=0; e<len; e++)
{
dat = 0xff;
Write_Data(dat); //to get an extra space between the
// numbers/letters for
//making it easier to read the text on the display
temp = str[e];
temp=temp-0x20; // As the lookup table starts from Space(0x20)
for (int w=0; w<5; w++)
{
dat= OledFontTable[temp][w]; // Get the data to be displayed for LookUptable
dat =~ dat;
Write_Data(dat);
}
}
}
----------
static uint8_t OledFontTable[][FONT_SIZE]={
//static uint8_t OledFontTable[] = {
0x00, 0x00, 0x00, 0x00, 0x00, // space
0x00, 0x00, 0x2f, 0x00, 0x00, // !
0x00, 0x07, 0x00, 0x07, 0x00, // "
0x14, 0x7f, 0x14, 0x7f, 0x14, // #
0x24, 0x2a, 0x7f, 0x2a, 0x12, // $
0x23, 0x13, 0x08, 0x64, 0x62, // %
0x36, 0x49, 0x55, 0x22, 0x50, // &
ETC. Etc.
just more raw pixel data here. this part ends like this:
0x00, 0x00, 0xFF, 0x00, 0x00, // |
0x00, 0x82, 0x7C, 0x10, 0x00, // }
0x00, 0x06, 0x09, 0x09, 0x06 // ~ (Degrees)
};
void Write_Data(unsigned char Data)
{
PORTA.OUTCLR = PIN7_bm; //cs
PORTB.OUTSET = PIN2_bm; //dc
Write_Command(Data); //
}
void Write_Command(unsigned char data)
{
SPI0.DATA = data; // copy data to DATA register
while ((SPI0.INTFLAGS & SPI_RXCIF_bm) == 0) ; //wait
}
I have asked a bit about this before. but i thought i would look "cleaner" with a new tread since info was missing from the last one.
It turned out I needed to toggle the chip select (CS) so the clock did not get out of sync with time.
The clock sync drifted with time.
It was going crazy faster for the non inverted data for some reason. But with the normal data it happend after some time also.
Thank you for the answers.
I had not problems with using nettle's twofish with standard ecb mode however i'm not sure what's wrong with this cbc mode? The decrypted message will not match the original. (using some hardcoded values like iv just for test purposes).
https://www.lysator.liu.se/~nisse/nettle/nettle.html
const uint8_t key[TWOFISH_KEY_SIZE] = {
0xea, 0xad, 0xdd, 0x6c, 0x32, 0x5a, 0xdc, 0x4f, 0x01, 0x5b, 0x4c,
0xde, 0xbb, 0x45, 0xc9, 0xe5, 0x5a, 0xb7, 0x5f, 0x3b, 0x01, 0x9a,
0xf8, 0x39, 0xd0, 0x74, 0x05, 0xeb, 0xf1, 0xaa, 0xa7, 0x67};
const uint8_t src[TWOFISH_BLOCK_SIZE] = {
0x3a, 0x53, 0xec, 0xae, 0xc0, 0xcf, 0xd3, 0xd8,
0xae, 0x05, 0x5d, 0xc0, 0x07, 0x3c, 0x04, 0x0d};
const uint8_t iv[TWOFISH_BLOCK_SIZE] = {
0xa0, 0xfb, 0x59, 0x3d, 0x70, 0x98, 0xdf, 0x8f,
0xff, 0xa0, 0x3b, 0xd5, 0xc5, 0x8b, 0x2c, 0x45};
uint8_t encrypted[TWOFISH_BLOCK_SIZE];
uint8_t decrypted[TWOFISH_BLOCK_SIZE];
struct CBC_CTX(struct twofish_ctx, TWOFISH_BLOCK_SIZE) ctx;
twofish256_set_key(&ctx.ctx, key);
CBC_SET_IV(&ctx, iv);
CBC_ENCRYPT(&ctx, twofish_encrypt, TWOFISH_BLOCK_SIZE, encrypted, src);
CBC_DECRYPT(&ctx, twofish_decrypt, TWOFISH_BLOCK_SIZE, decrypted,
encrypted);
for(int i = 0; i < TWOFISH_BLOCK_SIZE; i++) {
printf("\n%hhX\n", src[i]);
printf("%hhX\n", encrypted[i]);
printf("%hhX\n-------------------", decrypted[i]);
}
James is right: you need to set the IV again before decryption. From the Nettle documentation:
The final ciphertext block processed is copied into iv before returning, so that large message be processed be a sequence of calls to cbc_encrypt.
I.e. the IV inside the crypto context is lost and replaced by the last block of ciphertext. Hence you need to set it to the correct value again.
Nettle is a low level library, so this construct makes sense; higher level libraries may use streaming or assume that you always provide the complete plaintext/ciphertext in the call.
I am attempting to write an array of char to a BMP file in C. The problem with this is that whilst 0x00 values are required for the file, it seems C interprets this as the end of string when writing to the file i.e. as a NULL char. Is there any way I can override this and have C rely purely on what I say is the number of char I wish to pass?
Code for writing the header to file (this function is executed in main);
void writeFile(void){
unsigned char bmp1[54] = {
0x42, 0x4D, 0x36, 0x00,
0x0C, 0x00, 0x00, 0x00,
0x00, 0x00, 0x36, 0x00,
0x00, 0x00, 0x28, 0x00,
0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x01, 0x00,
0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x0C, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00
};
FILE *picFile = fopen("pic.bmp","w");
fprintf(picFile, bmp1, 54);
fclose(picFile);
}
Don't use fprintf() to write binary data, of course it's going to interpret its formatting string as a string. That's what it does!
Use fwrite(), and open your file in binary mode with "wb".
You can use sizeof to compute the size of the array, no need to hardcode the value:
FILE *picFile = fopen("pic.bmp", "wb");
if(picFile != NULL)
fwrite(bmp1, sizeof bmp1, 1, picFile);
fclose(picFile);
This works because it's in the same scope as the array declaration of bmp1.
The function fprintf() and its relatives are used to format some information and produce a string then write its characters1 into a file or put it on screen or store it into a given array of characters.
Use function fwrite() to write binary data; this function does not interpret the data you give it in any way and just writes the number of bytes you specify into the file.
Try this:
FILE *picFile = fopen("pic.bmp","w");
fwrite(bmp1, sizeof(bmp1), 1, picFile);
fclose(picFile);
(your call to fprintf() was erroneous, anyway)
1
The functions sprintf() and snprintf() (they put the generated string into a provided buffer of characters) copy the entire generated string onto their destination buffer, including the null terminating character.
The functions fprintf() (writes the string into a file) and printf() (puts the string on screen) do not put the null terminating character of the generated string into the output stream.
(Thanks #chux for pointing out that the C strings include the null terminating character.)
How would one go about taking hex data into a program and sending it back out?
char peer0_0[] = {
0x00, 0x00, 0x10, 0x01, 0xbf, 0x8b, 0xf9, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x07 };
char peer0_1[] = {
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 };
char peer0_2[] = {
0x02, 0x00, 0x00, 0x00 };
If you already have the code in the format you have posted, then there's not much to do. You haven't actually specified where you want to replay it. Depending on how you want to do this, you simply pass the array to whatever function does the actual sending. For example, if you want to send this data over an existing socket, you can do something like this:
send(my_socket, peer0_0, sizeof(peer0_0), 0);
What you want is bit-twist. It is essentially a replay device for pcap files. You don't have to save the file in any special format, it can be used with the native file format wireshark captures data in.
http://bittwist.sourceforge.net/