I've been trying to modify the tcp server example with LwIP in STM32F4DISCOVERY board. I have to write a sender which does not necessarily have to reply server responses. It can send data with 100 ms frequency, for example.
Firstly, the example of TCP server is like this:
static void tcpecho_thread(void *arg)
{
struct netconn *conn, *newconn;
err_t err;
LWIP_UNUSED_ARG(arg);
/* Create a new connection identifier. */
conn = netconn_new(NETCONN_TCP);
if (conn!=NULL) {
/* Bind connection to well known port number 7. */
err = netconn_bind(conn, NULL, DEST_PORT);
if (err == ERR_OK) {
/* Tell connection to go into listening mode. */
netconn_listen(conn);
while (1) {
/* Grab new connection. */
newconn = netconn_accept(conn);
/* Process the new connection. */
if (newconn) {
struct netbuf *buf;
void *data;
u16_t len;
while ((buf = netconn_recv(newconn)) != NULL) {
do {
netbuf_data(buf, &data, &len);
//Incoming package
.....
//Check for data
if (DATA IS CORRECT)
{
//Reply
data = "OK";
len = 2;
netconn_write(newconn, data, len, NETCONN_COPY);
}
} while (netbuf_next(buf) >= 0);
netbuf_delete(buf);
}
/* Close connection and discard connection identifier. */
netconn_close(newconn);
netconn_delete(newconn);
}
}
} else {
printf(" can not bind TCP netconn");
}
} else {
printf("can not create TCP netconn");
}
}
I modified this code to obtain a client version, this is what I've got so far:
static void tcpecho_thread(void *arg)
{
struct netconn *xNetConn = NULL;
struct ip_addr local_ip;
struct ip_addr remote_ip;
int rc1, rc2;
struct netbuf *Gonderilen_Buf = NULL;
struct netbuf *gonderilen_buf = NULL;
void *b_data;
u16_t b_len;
IP4_ADDR( &local_ip, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3 );
IP4_ADDR( &remote_ip, DEST_IP_ADDR0, DEST_IP_ADDR1, DEST_IP_ADDR2, DEST_IP_ADDR3 );
xNetConn = netconn_new ( NETCONN_TCP );
rc1 = netconn_bind ( xNetConn, &local_ip, DEST_PORT );
rc2 = netconn_connect ( xNetConn, &remote_ip, DEST_PORT );
b_data = "+24C"; // Data to be send
b_len = sizeof ( b_data );
while(1)
{
if ( rc1 == ERR_OK )
{
// If button pressed, send data "+24C" to server
if (GPIO_ReadInputDataBit (GPIOA, GPIO_Pin_0) == Bit_SET)
{
Buf = netbuf_new();
netbuf_alloc(Buf, 4); // 4 bytes of buffer
Buf->p->payload = "+24C";
Buf->p->len = 4;
netconn_write(xNetConn, Buf->p->payload, b_len, NETCONN_COPY);
vTaskDelay(100); // To see the result easily in Comm Operator
netbuf_delete(Buf);
}
}
if ( rc1 != ERR_OK || rc2 != ERR_OK )
{
netconn_delete ( xNetConn );
}
}
}
While the writing operation works, netconn_write sends what's on its buffer. It doesnt care whether b_data is NULL or not. I've tested it by adding the line b_data = NULL;
So the resulting output in Comm Operator is like this:
Rec:(02:47:27)+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C+24C
However, I want it to work like this:
Rec:(02:47:22)+24C
Rec:(02:47:27)+24C
Rec:(02:57:12)+24C
Rec:(02:58:41)+24C
The desired write operation happens when I wait for around 8 seconds before I push the button again.
Since netconn_write function does not allow writing to a buffer, I'm not able to clear it. And netconn_send is only allowed for UDP connections.
I need some guidance to understand the problem and to generate a solution for it.
Any help will be greately appreciated.
It's just a matter of printing the result in the correct way.
You can try to add this part of code before writing in the netbuf data structure:
char buffer[20];
sprintf(buffer,"24+ \n");
Buf->p->payload = "+24C";
I see one or two problems in your code, depending on what you want it exactly to do. First of all, you're not sending b_data at all, but a constant string:
b_data = "+24C"; // Data to be send
and then
Buf->p->payload = "+24C";
Buf->p->len = 4;
netconn_write(xNetConn, Buf->p->payload, b_len, NETCONN_COPY);
b_data is not anywhere mentioned there. What is sent is the payload. Try Buf->p->payload = b_data; if it's what you want to achieve.
Second, if you want the +24C text to be sent only once when you push the button, you'll have to have a loop to wait for the button to open again before continuing the loop, or it will send +24C continuously until you stop pushing the button. Something in this direction:
while (GPIO_ReadInputDataBit (GPIOA, GPIO_Pin_0) == Bit_SET) {
vTaskDelay(1);
}
Related
I have a master device and ESP32 acting as a slave, communicating directly over UART with RX/TX cables. I've created a task that checks the serial stream every 50 ms and parses the data. My problem is that the serial stream freezes up, seemingly randomly, and only restarts if the master or the slave are restarted.
The task looks as such:
void TaskListen_UART(void *pvParameters)
{
while (true)
{
if (readSerialIn())
{
slaveRunCommand(serialData.command); // Execute received commmand
}
vTaskDelay(50 / portTICK_PERIOD_MS);
}
}
It checks the serial stream through readSerialIn() which looks like the following:
bool readSerialIn()
{
if (UART.available() > 0) // Check if the Serial port received data
{
serialData.clearStruct(); // Clear previously saved data
if (UART.find(0x2A)) // Find "*" // Find starting delimiter
{
serialData.length = UART.read(); // Read length
if (serialData.length > BYTE_BUFFER_LEN)
{
writeSerialNACK(); // Write NACK if length seems incorrect
return false;
}
Serial.printf(("Message length: %d\n"), serialData.length);
serialData.checksum = UART.read(); // Read Checksum
Serial.printf(("Checksum: %d\n"), serialData.checksum);
if (parseBuffer(serialData.length)) // Parse the data
{
if (serialData.checkSum()) // If the checksum passes
{
serialData.assignBuffer(); // Save the parsed data to the global buffer
return true;
}
else
{
writeSerialNACK();
return false;
}
}
else
false;
}
else
return false;
}
}
The parseBuffer() function is what actually reads the stream and parses it into their according values on the slave. I tried to write it in the most fail-safe fashion, but it still hasn't cleared up my issue.
bool parseBuffer(uint8_t bufferLength)
{
uint8_t bufferPos = 0;
bool uartDetectFlag = false;
while (UART.available() > 0)
{
uartDetectFlag = true;
if (bufferPos < bufferLength)
{
serialData.serialBuffer[bufferPos] = UART.read();
}
bufferPos++;
}
if (uartDetectFlag)
return true;
else
return false;
}
At first I was suspicious that the ESP was trying to access a block in memory that doesn't exist. I noticed however that it doesn't reset itself like it normally would if that were the case, and I tried writing parseBuffer in a non-blocking manner. I also tried increasing the task delay to 100 ms, which reduced the frequency of the blocking but did not suffice in terms of speed. Regardless, it freezes up and (I think) it's caused by a large flow of data through the serial stream.
I want to use sync encryption in linux kernel (since the code is run in interrupt context, which cannot sleep). Under /proc/crypto, there are several candidates which is marked sync, like __gcm(aes), __ctr(aes), __xts(aes). I tried to use this code example in kernel crypto API documentation, but get error when trying to allocate tfm using crypto_alloc_req. The code is as below:
static int test_skcipher(void)
{
struct crypto_skcipher *tfm = NULL;
struct skcipher_request *req = NULL;
u8 *data = NULL;
const size_t datasize = 512; /* data size in bytes */
struct scatterlist sg;
DECLARE_CRYPTO_WAIT(wait);
u8 iv[16]; /* AES-256-XTS takes a 16-byte IV */
u8 key[64]; /* AES-256-XTS takes a 64-byte key */
int err;
/*
* Allocate a tfm (a transformation object) and set the key.
*
* In real-world use, a tfm and key are typically used for many
* encryption/decryption operations. But in this example, we'll just do a
* single encryption operation with it (which is not very efficient).
*/
tfm = crypto_alloc_skcipher("__xts(aes)", 0, 0);
if (IS_ERR(tfm)) {
pr_err("Error allocating xts(aes) handle: %ld\n", PTR_ERR(tfm));
return PTR_ERR(tfm);
}
get_random_bytes(key, sizeof(key));
err = crypto_skcipher_setkey(tfm, key, sizeof(key));
if (err) {
pr_err("Error setting key: %d\n", err);
goto out;
}
/* Allocate a request object */
req = skcipher_request_alloc(tfm, GFP_KERNEL);
if (!req) {
err = -ENOMEM;
goto out;
}
/* Prepare the input data */
data = kmalloc(datasize, GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto out;
}
get_random_bytes(data, datasize);
/* Initialize the IV */
get_random_bytes(iv, sizeof(iv));
/*
* Encrypt the data in-place.
*
* For simplicity, in this example we wait for the request to complete
* before proceeding, even if the underlying implementation is asynchronous.
*
* To decrypt instead of encrypt, just change crypto_skcipher_encrypt() to
* crypto_skcipher_decrypt().
*/
sg_init_one(&sg, data, datasize);
skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
CRYPTO_TFM_REQ_MAY_SLEEP,
crypto_req_done, &wait);
skcipher_request_set_crypt(req, &sg, &sg, datasize, iv);
err = crypto_wait_req(crypto_skcipher_encrypt(req), &wait);
if (err) {
pr_err("Error encrypting data: %d\n", err);
goto out;
}
pr_debug("Encryption was successful\n");
out:
crypto_free_skcipher(tfm);
skcipher_request_free(req);
kfree(data);
return err;
}
This code is basically the same as the document, only replacing xts(aes) with __xts(aes). I have already checked that __xts(aes) appears in /proc/crypto, but it seems kernel cannot find the corresponding algorithm. Is there any other documentation about how to use sync skcipher inside linux kernel? A working code example will be appreciated.
Today I have spent a lot of time on the same issue and during my "No-Straightforward-Documentation-Blues". I found your almost-the-same story here and without any reply (omg....). Thus, if you are still facing this problem, I hope it will be helpful.
GCM is about an AEAD cipher operation mode and this operation mode also reflects into linux/crypto. The transformations done by using skcipher is not suitable for GCM. AEAD does much more than just encrypt/decrypt data. It is capable of authenticating. So skcipher cannot "see" ciphers working under GCM mode, because it does not know how to handle them. So if you try to get a transformation handle for GCM by using skcipher, it will say "gc what?! gc who?!!". It is clearer now, because I also was considering that skcipher was about a meta data transformation stuff, but it is not. There is another "tfm" (poorly documented, btw) that can attend us.
Linux crypto api offers struct crypto_aead. The crypto_aead has all its correspondent convenience functions that skcipher has. In general it is almost the "same". However, it is necessary taking into consideration the particularities of GCM and how it is organized into crypto_aead stuff. Anyway, it is not so arcane (if you already know some aspects of the concepts behind of AEAD/GCM and I am taking into consideration that you know). Take a look:
int do_aes_gcm_min_sample(void) {
struct crypto_aead *tfm = NULL;
struct aead_request *req = NULL;
u8 *buffer = NULL;
size_t buffer_size = TEST_DATA_SIZE;
u8 *bp = NULL, *bp_end = NULL;
struct scatterlist sg = { 0 };
DECLARE_CRYPTO_WAIT(wait);
// INFO(Rafael): The majority of AES/GCM implementation uses 12 bytes iv (crypto_aead_ivsize()
// returned this, so for this reason I am using this "magic" value here.)
u8 iv[12] = { 0 };
u8 key[32] = { 0 }; // INFO(Rafael): The version of AES is defined by the size (in bytes) of the
// informed key. So, here we are using AES-256.
int err = -1;
tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
if (IS_ERR(tfm)) {
err = PTR_ERR(tfm);
pr_err("AES/GCM min sample: crypto_alloc_aead() has failed: %d.\n", err);
goto do_aes_gcm_min_sample_epilogue;
}
// INFO(Rafael): Telling to api how many bytes will compound our MAC (a.k.a tag etc [etc no!...]).
err = crypto_aead_setauthsize(tfm, AES_GCM_TAG_SIZE);
if (err != 0) {
pr_err("AES/GCM min sample: crypto_aead_setauthsize() has failed: %d.\n", err);
goto do_aes_gcm_min_sample_epilogue;
}
// WARN(Rafael): In practice it could come from a `KDF(weak_usr_password)` stuff.
// Never ever use directly the "key" informed by the user.
// It demolishes the good will of any crypto algorithm on
// doing good encryption. Let's value hard work of cryptographers on
// seeking to create state of the art ciphers ;), please!
// So, I am only getting the key from a csprng that is a thing
// near to what an alleged good KDF is able to do with a weak password
// or at least must do.
get_random_bytes(key, sizeof(key));
err = crypto_aead_setkey(tfm, key, sizeof(key));
if (err != 0) {
pr_err("AES/GCM min sample: crypto_aead_setkey() has failed: %d.\n", err);
goto do_aes_gcm_min_sample_epilogue;
}
req = aead_request_alloc(tfm, GFP_KERNEL);
if (req == NULL) {
err = -ENOMEM;
pr_err("AES/GCM min sample: aead_request_alloc() has failed.\n");
goto do_aes_gcm_min_sample_epilogue;
}
req->assoclen = 0; // INFO(Rafael): No associated data, just reinforcing it.
// Anyway, when you want to also authenticated
// plain data (a.k.a AAD, associated data) you
// must indicate the size in bytes of the
// aad here and prepend your plaintext with
// aad.
get_random_bytes(iv, sizeof(iv));
// INFO(Rafael): The AES/GCM encryption primitive will also spit at the end of
// the encrypted buffer the n bytes asked tags generated by GHASH.
// Since we are using the same buffer for output stuff, this buffer
// must be able to fit the input and ***also*** the result.
buffer_size = TEST_DATA_SIZE + AES_GCM_TAG_SIZE;
buffer = kmalloc(buffer_size, GFP_KERNEL);
if (buffer == NULL) {
err = -ENOMEM;
pr_err("AES/GCM min sample: kmalloc() has failed.\n");
goto do_aes_gcm_min_sample_epilogue;
}
// INFO(Rafael): Copying the one block input...
memcpy(buffer, TEST_DATA, TEST_DATA_SIZE);
bp = buffer;
bp_end = bp + TEST_DATA_SIZE;
// INFO(Rafael): Currently buffer contains only the one dummy test block. Right?...
pr_info("Original data: ");
while (bp != bp_end) {
pr_info("%c\n", isprint(*bp) ? *bp : '.');
bp++;
}
// INFO(Rafael): ...however our scattterlist must be initialised
// by indicating the whole allocated buffer segment (including room
// for the tag). Because it will also output data, got it?
sg_init_one(&sg, buffer, buffer_size);
aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
CRYPTO_TFM_REQ_MAY_SLEEP, crypto_req_done, &wait);
// INFO(Rafael): Thus, for ***encrypting*** our input buffer is
// `TEST_DATA_SIZE == buffer_size - AES_GCM_TAG_SIZE`,
// since
// `buffer_size == TEST_DATA_SIZE + AES_GCM_TAG_SIZE`.
aead_request_set_crypt(req, &sg, &sg, buffer_size - AES_GCM_TAG_SIZE, iv);
err = crypto_wait_req(crypto_aead_encrypt(req), &wait);
if (err != 0) {
pr_err("AES/GCM min sample: error when encrypting data: %d.\n", err);
goto do_aes_gcm_min_sample_epilogue;
}
// INFO(Rafael): If aad would be also passed it would prepend the cryptogram.
// req-assoclen give you the clue of traverse or even skip it.
pr_info("Cryptogram: ");
// INFO(Rafael): Now buffer contains the authenticated cryptogram. I meant <cryptogram><MAC>.
// Here the intention is only print the cryptogram.
bp = buffer;
bp_end = bp + buffer_size - AES_GCM_TAG_SIZE;
while (bp != bp_end) {
pr_info("%c\n", isprint(*bp) ? *bp : '.');
bp++;
}
pr_info("Authentication tag: ");
// INFO(Rafael): Since bp is already pointing to the first byte of what should be the tag, let's only moving
// AES_GCM_TAG_SIZE bytes ahead the end marker of the output buffer.
bp_end += AES_GCM_TAG_SIZE;
while (bp != bp_end) {
pr_info("%c\n", isprint(*bp) ? *bp : '.');
bp++;
}
// INFO(Rafael): I hate incomplete samples, so let's decrypt, too.
// Decrypting with GCM involves checking if the tag informed at the end of cryptogram,
// is really the same of the on-the-fly calculated by GHASH. Thus, when decrypting the
// is necesary to indicate the cryptogram and ***also*** the tag, so here its size is
// expressed by buffer_size.
aead_request_set_crypt(req, &sg, &sg, buffer_size, iv);
// INFO(Rafael): What about testing if GCM is really detecting tampered data?
// Give it a try by uncomment all or even one of the following three lines.
//key[sizeof(key) >> 1] += 1;
//buffer[buffer_size >> 1] += 1;
//buffer[buffer_size - AES_GCM_TAG_SIZE + 1] += 1; // INFO(Rafael): Bit flipping MAC.
// INFO(Rafael): For the context of this sample, it would not be necessary. Anyway, we want to test
// corrupted key cases.
err = crypto_aead_setkey(tfm, key, sizeof(key));
if (err != 0) {
pr_err("AES/GCM min sample: crypto_aead_setkey() has failed: %d.\n", err);
goto do_aes_gcm_min_sample_epilogue;
}
err = crypto_wait_req(crypto_aead_decrypt(req), &wait);
if (err != 0) {
pr_err("AES/GCM min sample: Error when decrypting data, it seems tampered. "
"Ask for a retransmission or verify your key.\n");
goto do_aes_gcm_min_sample_epilogue;
}
// INFO(Rafael): If aad would be also passed it would prepend the plaintext.
// req->assoclen give you the clues of how to traverse or even
// skipping it. But even skipped it must be passed by the
// decryption routine. Because it also authenticates the whole
// buffer, got it?
pr_info("Authenticated plaintext: ");
bp = buffer;
bp_end = bp + buffer_size - AES_GCM_TAG_SIZE; // INFO(Rafael): It will not reallocate the buffer so, let's exclude the MAC.
// Due to it maybe should be good to ensure a buffer_size multiple of four.
// It would keep this simpler. Anyway you can apply a more sophisticated
// padding technique, but for this sample I think it express the main idea.
while (bp != bp_end) {
pr_info("%c\n", isprint(*bp) ? *bp : '.');
bp++;
}
do_aes_gcm_min_sample_epilogue:
if (req != NULL) {
aead_request_free(req);
}
if (tfm != NULL) {
crypto_free_aead(tfm);
}
if (buffer != NULL) {
kfree(buffer);
}
return err;
}
If you want to test quickly, you can clone this sample repo here.
I also have tried to run this code on kernel 4.4.14 (it has needed some minor workarounds, it seems fine, but I did not tested it a lot). For the sake of brevity I will not comment what I done but if you are interested feel free on cloning the repo and grasp into those "hacks". But the code is only a sample, much more must be done to deliver a good crypto there, avoid copying and pasting, please.
I am trying to implement a TCP server using C in Linux. I want this server to accept incoming data forever from multiple clients and at the same time send some data back to each connected client in every 3 seconds.
My problem is I don't know how to properly do send() in a different process than the one handling the client.
What I am doing is at the beginning of the program do a fork() and do
while (1) {
sleep(3);
// compute and `send()` data to each connected peers
}
in child process, do
sock = create_socket();
while (1) {
client_sock = accept_connection(sock);
if (fork() == 0) {
close(sock);
handle_client(client_sock);
exit(0);
}
close(client_sock);
// clean up zombies
}
in parent process. handle_client() is simply recv() data in a infinite loop. Because send() and recv() are executed in different processes, I couldn't use the socket file descriptors to send() in parent process. What do I need to do in the parent process to do the send()?
You have three levels of processes, a parent, a child, and many grandchildren. Get rid of these levels, and do not fork at all; instead using an event-driven model in a single process.
In rough pseudo-code (translate to your preferred language):
listening_fd = create_socket();
EventQueueOfSomeKind q; // kqueue()-style
q.add_or_update_event(listening_fd, EVFILT_READ, EV_ENABLE);
q.add_or_update_event(3, EVFILT_TIMER, EV_ENABLE, NOTE_SECONDS);
FDToContextMapOfSomeKind context_map;
EventVector event_vector; // vector of kevent-like things
while (1) {
q.wait_for_events(&event_vector); // kevent()-style
foreach e <- event_vector {
switch (e.type) {
case EVFILT_READ:
if (listening_fd == e.fd) {
client_sock = accept_connection(e.fd, SOCK_NONBLOCK);
q.add_or_update_event(client_sock, EVFILT_READ, EV_ENABLE);
q.add_or_update_event(client_sock, EVFILT_WRITE, EV_DISABLE);
context_map.add_new_context(client_socket);
} else {
// Must be one of the client sockets
if (e.flags & EV_EOF) {
context_map.remove_context(e.fd);
q.remove_event(e.fd, EVFILT_READ);
q.remove_event(e.fd, EVFILT_WRITE);
close(e.fd);
} else {
recv(e.fd, buffer);
handle_client_input(&context_map[e.fd], buffer);
}
}
break;
case EVFILT_WRITE:
if (has_queued_output(context_map[e.fd])) {
send(e.fd, pull_queued_output(&context_map[e.fd]));
} else {
q.add_or_update_event(client_sock, EVFILT_WRITE, EV_DISABLE);
}
break;
case EVFILT_TIMER:
foreach client_sock,context <- context_map {
push_queued_output(&context, computed_data(context));
q.add_or_update_event(client_sock, EVFILT_WRITE, EV_ENABLE);
}
break;
}
}
}
I have glossed over partial send()s and recv()s, write-side shutdown, and all error handling but this is the general idea.
Further reading
https://github.com/mheily/libkqueue
Jonathan Lemon. kqueue. OpenBSD System Calls Manual.
Jonathan Lemon. kqueue. Darwin BSD Calls Manual. Apple corporation.
This is a solution using Linux epoll and timerfd (error handling is omitted):
int start_timer(unsigned int interval) {
int tfd;
struct itimerspec tspec;
tspec.it_value.tv_sec = 1;
tspec.it_value.tv_nsec = 0;
tspec.it_interval.tv_sec = 3;
tspec.it_interval.tv_nsec = 0;
tfd = timerfd_create(CLOCK_MONOTONIC, 0);
timerfd_settime(tfd, TFD_TIMER_ABSTIME, &tspec, NULL);
return tfd;
}
void epset_add(int epfd, int fd, uint32_t events)
{
struct epoll_event ev;
ev.data.fd = fd;
ev.events = events;
epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev);
}
int main()
{
int epfd, tfd, sock, nfds, i;
struct epoll_event events[MAX_EVENTS];
/* create new epoll instance */
epfd = epoll_create1(0);
tfd = start_timer(TIMER_INTERVAL);
/* socket(), bind() and listen() omitted in create_socket() */
sock = create_socket(PORT_NUMBER);
/* add sock and tfd to epoll set */
epset_add(epfd, tfd, EPOLLIN);
epset_add(epfd, sock, EPOLLIN | EPOLLET);
for (;;) {
for (i = 0; i < nfds; ++i) {
if (events[i].data.fd == tfd) {
/* handle timer notification, it's run
periodically with interval TIMER_INTERVAL */
} else if (events[i].data.fd == sock) {
/* accept() incoming connections,
set non-blocking,
and add new connection sockets to epoll set */
} else {
/* recv() from connection sockets and handle */
}
}
}
}
This program was helpful https://github.com/eklitzke/epollet/blob/master/poll.c and I added timerfd to the epoll set so the server keeps listening and receiving data and at the same time can send data to the clients periodically.
I'm new to QT and I'm trying to create an encrypted function.
Overall what you do in C / C ++ is:
Take pointer to function
make the function page rwx
Encrypt it (for the example I encrypt and decrypt in the same program)
Decrypt it and run it
A simple code in C will happen roughly like this:
void TestFunction()
{
printf("\nmsgbox test encrypted func\n");
}
// use this as a end label
void FunctionStub() { return; }
void XorBlock(DWORD dwStartAddress, DWORD dwSize)
{
char * addr = (char *)dwStartAddress;
for (int i = 0; i< dwSize; i++)
{
addr[i] ^= 0xff;
}
}
DWORD GetFuncSize(DWORD* Function, DWORD* StubFunction)
{
DWORD dwFunctionSize = 0, dwOldProtect;
DWORD *fnA = NULL, *fnB = NULL;
fnA = (DWORD *)Function;
fnB = (DWORD *)StubFunction;
dwFunctionSize = (fnB - fnA);
VirtualProtect(fnA, dwFunctionSize, PAGE_EXECUTE_READWRITE, &dwOldProtect); // make function page read write execute permission
return dwFunctionSize;
}
int main()
{
DWORD dwFuncSize = GetFuncSize((DWORD*)&TestFunction, (DWORD*)&FunctionStub);
printf("use func");
TestFunction();
XorBlock((DWORD)&TestFunction, dwFuncSize); // XOR encrypt the function
printf("after enc");
//TestFunction(); // If you try to run the encrypted function you will get Access Violation Exception.
XorBlock((DWORD)&TestFunction, dwFuncSize); // XOR decrypt the function
printf("after\n");
TestFunction(); // Fine here
getchar();
}
When I try to run such an example in QT I get a run time error.
Here is the code in QT:
void TestFunction()
{
QMessageBox::information(0, "Test", "msgbox test encrypted func");
}
void FunctionStub() { return; }
void XorBlock(DWORD dwStartAddress, DWORD dwSize)
{
char * addr = (char *)dwStartAddress;
for (int i = 0; i< dwSize; i++)
{
addr[i] ^= 0xff; // here i get seg. fault
}
}
DWORD GetFuncSize(DWORD* Function, DWORD* StubFunction)
{
DWORD dwFunctionSize = 0, dwOldProtect;
DWORD *fnA = NULL, *fnB = NULL;
fnA = (DWORD *)Function;
fnB = (DWORD *)StubFunction;
dwFunctionSize = (fnB - fnA);
VirtualProtect(fnA, dwFunctionSize, PAGE_EXECUTE_READWRITE, &dwOldProtect); // Need to modify our privileges to the memory
QMessageBox::information(0, "Test", "change func to read write execute ");
return dwFunctionSize;
}
void check_enc_function()
{
DWORD dwFuncSize = GetFuncSize((DWORD*)&TestFunction, (DWORD*)&FunctionStub);
QMessageBox::information(0, "Test", "use func");
TestFunction();
XorBlock((DWORD)&TestFunction, dwFuncSize); // XOR encrypt the function -> ### i get seg fault in here ###
QMessageBox::information(0, "Test", "after enc");
TestFunction(); // If you try to run the encrypted function you will get Access Violation Exception.
XorBlock((DWORD)&TestFunction, dwFuncSize); // XOR decrypt the function
QMessageBox::information(0, "Test", "after dec");
TestFunction(); // Fine here
getchar();
}
Why should this happen?
QT is supposed to behave like precision as standard C ++ ...
post Scriptum.
Interestingly in the same matter, what is the most legitimate way to keep an important function encrypted (the reason it is encrypted is DRM)?
Legitimately I mean that anti-viruses will not mistakenly mark me as a virus because I defend myself.
PS2
If I pass an encrypted function over the network (say, I will build a server client schema that the client asks for the function it needs to run from the server and the server sends it to it if it is approved) How can I arrange the symbols so that the function does not collapse?
PS3
How in QT can I turn off the DEP and ASLR defenses? (In my opinion so that I can execute PS 2. I have to cancel them)
Thanks
yoko
The example is undefined behaviour on my system.
The first and main issue in your code is:
void TestFunction() { /* ... */ }
void FunctionStub() { return; }
You assume that the compiler will put FunctionStub after TestFunction without any padding. I compiled your example and FunctionStub in my case was above TestFunction which resulted in a negative dwFunctionSize.
dwFunctionSize = (fnB - fnA);
TestFunction located at # 0xa11d90
FunctionStub located at # 0xa11b50
dwFunctionSize = -0x240
Also in XorBlock
addr[i] ^= 0xff;
Is doing nothing.
I assume you want to write in XorBlock to the memory location to XOR the entire TestFunction.
You could do something like this:
void XorBlock(DWORD dwStartAddress, DWORD dwSize)
{
DWORD dwEndAddress = dwStartAddress + dwSize;
for(DWORD i = dwStartAddress; i < dwEndAddress; i++) {
// ...
}
}
I can't see any Qt-specific in your example. Even if it's Qt function call it's just a call. So I guess you have undefined behaviour in both examples but only second one crashes.
I can't see any reason for compiler and linker to keep function order. For example GCC let you specify the code section for each function. So you can reorder it in executable without reordering in cpp.
I think you need some compiler specific things to make it work.
I am trying to modify the multihop Oscilloscope program so that the sink node is able to send data both to UART and radio medium as well. As far as researched, I found out that the same hardware is used for sending packets via UART and radio too.
In this case, how do I modify my code so that I can send data to UART or radio based on a condition I receive. Here in the sample prorgram, I send data via radio on every 10 packets received.
The receive module for my sink node is:
event message_t* Receive.receive(message_t* msg, void *payload, uint8_t len) {
oscilloscope_t* in = (oscilloscope_t*)payload;
counter++;
am_addr_t rec = call AMPacket.source(msg);
oscilloscope_t* out;
counter++;
call Leds.led0On();
if (uartbusy == FALSE) {
out = (oscilloscope_t*)call SerialSend.getPayload(&uartbuf, sizeof(oscilloscope_t));
if (len != sizeof(oscilloscope_t) || out == NULL) {
return msg;
}
else {
memcpy(out, in, sizeof(oscilloscope_t));
}
uartlen = sizeof(oscilloscope_t);
post uartSendTask();
} else {
message_t *newmsg = call UARTMessagePool.get();
if (newmsg == NULL) {
report_problem();
return msg;
}
//Serial port busy, so enqueue.
out = (oscilloscope_t*)call SerialSend.getPayload(newmsg, sizeof(oscilloscope_t));
if (out == NULL) {
return msg;
}
memcpy(out, in, sizeof(oscilloscope_t));
if (call UARTQueue.enqueue(newmsg) != SUCCESS) {
call UARTMessagePool.put(newmsg);
fatal_problem();
return msg;
}
}
if(counter % 10 == 0){
oscilloscope_t* btrpkt = (oscilloscope_t*)(call Packet.getPayload(&pkt, sizeof(oscilloscope_t)));
call Leds.led1On();
if (call AMSend.send(rec, &pkt, sizeof(oscilloscope_t)) == SUCCESS) {
call Leds.led0On();
sendbusy = TRUE;
}
}
return msg;
}
Once the data sends back to the node from where it received the packet , it is unable to process it through UART again. Could anyone help me how could I solve my problem?
According to the question and comments:
You must instantiate AMSenderC with the same id as for the receiver. In this case, AM_OSCILLOSCOPE if you want a message to be processed by the same code. Or another id plus a new implementation of the Receive interface.
You missed putting payload into btrpkt.
You must check for sendbusy - it is a bug if you try to use the radio stack when it is busy.