This is an exercise that I want to implement in real code
I send a signal to my app (x86-64 linux). My app then executes code that walks the stack and prints out instruction pointers. I'm not sure if I want only the last few or everything to main. Anyway, I'm releasing an optimized binary without debug information. I strip symbols before its distributed.
I was wondering, how do I translate it back? I don't need to translate it in the app. I can use the machine I build to go from rip's to functions. I was thinking maybe I should also distribute one with debug information and maybe have the user be able to see the function+line but I think line will be unlikely if its optimized well
Another problem I have is my code doesn't seem to walk past the signal function. backtrace figures it out but I'm trying to do this without libc. Here's some code
#include <signal.h>
#include <cstdio>
typedef unsigned long long u64;
int mybacktrace();
#include <execinfo.h>
#include <unistd.h>
void print_stacktrace(void) {
size_t size;
enum Constexpr { MAX_SIZE = 1024 };
void *array[MAX_SIZE];
size = backtrace(array, MAX_SIZE);
backtrace_symbols_fd(array, size, STDOUT_FILENO);
}
void mysig(int signo) {
mybacktrace();
_exit(1);
}
int mybacktrace() {
u64*p;
p = (u64*)((u64)&p + 16); //seems to work correctly
for (int i = 0; i < 10 && (u64)p >= 1<<16; i++)
{
printf("%d %p\n", i, p[1]);
p = (u64*)(p[0]);
}
print_stacktrace(); return 0;
return 0;
}
int test()
{
return mybacktrace();
}
int main(int argc, char *argv[])
{
signal(SIGILL, mysig);
test();
__builtin_trap();
return 0;
}
I'm trying to run the code demo for ICU4C bellow, and getting
warning: implicit declaration of function 'austrdup'
which subsequently generate an error. I understand that this is due to the missing imported library that contains 'austrdup' function, and have been looking at the source code to guess which one it is, but no luck. Does anyone have any idea which one should be imported?
#include <unicode/umsg.h>
#include <unicode/ustring.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{
UChar* str;
UErrorCode status = U_ZERO_ERROR;
UChar *result = NULL;
UChar pattern[100];
int32_t resultlength, resultLengthOut, i;
double testArgs[] = { 100.0, 1.0, 0.0};
str=(UChar*)malloc(sizeof(UChar) * 10);
u_uastrcpy(str, "MyDisk");
u_uastrcpy(pattern, "The disk {1} contains {0,choice,0#no files|1#one file|1<{0,number,integer} files}");
for(i=0; i<3; i++){
resultlength=0;
resultLengthOut=u_formatMessage( "en_US", pattern, u_strlen(pattern), NULL, resultlength, &status, testArgs[i], str);
if(status==U_BUFFER_OVERFLOW_ERROR){ //check if output truncated
status=U_ZERO_ERROR;
resultlength=resultLengthOut+1;
result=(UChar*)malloc(sizeof(UChar) * resultlength);
u_formatMessage( "en_US", pattern, u_strlen(pattern), result, resultlength, &status, testArgs[i], str);
}
printf("%s\n", austrdup(result) ); //austrdup( a function used to convert UChar* to char*)
free(result);
}
return 0;
}
austrdup is not an official ICU method. It's only used by tests in ICU and defined in icu4c/source/test/cintltst/cintltst.h and implemented in icu4c/source/test/cintltst/cintltst.c. It is bascially just a wrapper around u_austrcpy.
I am trying to add an IPv6 address to an ethernet interface, using libmnl. After constructing a message and sending to the kernel, I saw that it was not added to the interface, even though the return codes for the kernel reply did not contain any error. Kindly can anybody have a look, and help me correct it. Am I supposed to add more attributes to the nlmsghdr or something else?
#include <assert.h>
#include <string.h>
#include <inttypes.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <libmnl/libmnl.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
#include <time.h>
static struct mnl_socket *nl;
static unsigned int nlportid;
int mnl_init(void);
int mnl_init(){
nl = mnl_socket_open(NETLINK_ROUTE);
if(nl == NULL){
printf("Error: mnl_socket_open\n");
return 0;
}
if(mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0){
printf("Error: mnl_socket_bind\n");
return 0;
}
nlportid = mnl_socket_get_portid(nl);
return 1;
}
int add_to_interface(const char* eip){
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
struct ifaddrmsg *ifm;
int ret;
uint8_t seq;
nlh = mnl_nlmsg_put_header(buf);
nlh->nlmsg_type = RTM_NEWADDR;
nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
nlh->nlmsg_seq = seq = time(NULL);
ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));
ifm->ifa_family = AF_INET6;
ifm->ifa_prefixlen = 64;
ifm->ifa_flags = IFA_F_PERMANENT;
ifm->ifa_scope = RT_SCOPE_UNIVERSE;
/* TODO get interaface name from user or configuration*/
ifm->ifa_index = if_nametoindex("eth0");
unsigned char eipn[16];
inet_pton(AF_INET6, eip, eipn);
mnl_attr_put(nlh, IFA_ADDRESS, 16,eipn);
mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct ifaddrmsg));
if(mnl_socket_sendto(nl,nlh, nlh->nlmsg_len) < 0){
printf("Error: mnl_socket_sendto");
return 0;
}
ret = mnl_socket_recvfrom(nl,buf, sizeof(buf));
if(ret == -1){
printf("Error: mnl_socket_recvfrom");
return 0;
}
ret = mnl_cb_run(buf, ret, seq, nlportid, NULL, NULL);
return 0;
}
int main(int argc, char *argv[]){
if(mnl_init()){
add_to_interface("2001::20c:29ff:fe5f:13c7/64"); // for testing
}
}
I don't really know anything about libmnl, and the following solution is not perfect. But in case you're still stuck...
Notice that you're dropping several error codes. This one, in particular:
inet_pton(AF_INET6, eip, eipn);
Should be something in the lines of this:
ret = inet_pton(AF_INET6, eip, eipn);
if (ret != 1) {
printf("Bad address.\n");
return -22;
}
And I suppose you can tell where I'm going with this. This:
add_to_interface("2001::20c:29ff:fe5f:13c7/64"); // for testing
Should be this:
add_to_interface("2001::20c:29ff:fe5f:13c7"); // for testing
That fixes it for me. Except it hags at mnl_socket_recvfrom() because the kernel does not answer, apparently.
But do be more careful with those error codes; the ones I mentioned aren't the only ones.
Solution from Pablo Neira,
eipn should be 'struct in6_addr' instead.
mnl_attr_put(nlh, IFA_ADDRESS, 16,eipn);
So this looks like:
mnl_attr_put(nlh, IFA_ADDRESS, sizeof(eipn), &eipn);
How can I modify the source code in the func( ) so that the address to which the program returns after executing func () is changed in such a manner that the instruction printf("first print\n”) is skipped. Use the pointer *ret defined in func() to modify the return address appropriately in order to achieve this.
Here is the code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void func(char *str)
{
char buffer[24];
int *ret;
strcpy(buffer,str);
}
int main(int argc, char **argv)
{
if (argc < 2)
{
printf("One argument needed.\n");
exit(0);
}
int x;
x = 0;
func(argv[1]);
x = 1;
printf("first print\n");printf("second print\n");
}
As sherrellbc noted, a program's exploits are usually written without modifying its source code. But if you want, inserting these two lines into func() may do:
ret = (int *)&str; // point behind saved return address
ret[-1] += 12; // or however many code bytes are to be skipped
Helo, i am trying to pass it like this
typedef struct t_timeSliceRequest{
unsigned int processId;
unsigned int timeRequired;
int priority;
}timeSliceRequest;
struct t_timeSliceRequest request = { 1,2,1 };
sendFlag = send(socketID,(timeSliceRequest *) &request, sin_size ,0);
and on server side
recvFlag = recv(socketID,(timeSliceRequest *) &request,sin_size,0);
but its receiving garbage, even recv returning -1, please help
This is my full Conde
#include<sys/socket.h>
#include<sys/types.h>
#include<string.h>
#include<stdio.h>
#include<arpa/inet.h>
#include<time.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>
enum priority_e{ high, normal, low };
typedef struct t_timeSliceRequest{
unsigned int processId;
unsigned int timeRequired;
int priority;
}timeSliceRequest;
typedef struct t_TimeSliceResponse {
timeSliceRequest original_req;
// Unix time stamp of when process was started on server
unsigned int time_started;
// Waiting and running time till end of CPU bust
unsigned int ttl;
} TimeSliceResponse;
int main(int argc, char ** argv){
int socketID = 0, clientID = 0;
char sendBuffer[1024], recvBuffer[1024];
time_t time;
struct sockaddr_in servAddr, clientAddr;
struct t_timeSliceRequest request = {1,1,0};
memset(sendBuffer, '0', sizeof(sendBuffer));
memset(recvBuffer, '0', sizeof(recvBuffer));
fprintf(stdout,"\n\n --- Server starting up --- \n\n");
fflush(stdout);
socketID = socket(AF_INET, SOCK_STREAM, 0);
if(socketID == -1){
fprintf(stderr, " Can't create Socket");
fflush(stdout);
}
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(5000);
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
int bindID, sin_size, recvFlag;
bindID = bind(socketID, (struct sockaddr *)&servAddr, sizeof(servAddr)); // Casting sockaddr_in on sockaddr and binding it with socket id
if(bindID!=-1){
fprintf(stdout," Bind SucessFull");
fflush(stdout);
listen(socketID,5);
fprintf(stdout, " Server Waiting for connections\n");
fflush(stdout);
while(1){
sin_size = sizeof(struct sockaddr_in);
clientID = accept(socketID, (struct sockaddr *) &clientAddr, &sin_size);
fprintf(stdout,"\n I got a connection from (%s , %d)", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));
fflush(stdout);
sin_size = sizeof(request);
recvFlag = recv(socketID, &request,sin_size,0);
perror("\n Err: ");
fprintf(stdout, "\n recvFlag: %d", recvFlag);
fprintf(stdout, "\n Time Slice request received:\n\tPid: %d \n\tTime Required: %d ", ntohs(request.processId), ntohs(request.timeRequired));
fflush(stdout);
snprintf(sendBuffer, sizeof(sendBuffer), "%.24s\n", ctime(&time));
write(clientID, sendBuffer, strlen(sendBuffer));
close(clientID);
sleep(1);
}
}else{
fprintf(stdout, " Unable to Bind");
}
close(socketID);
return 0;
}
And Client Code is:
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
enum priority_e{ high = +1, normal = 0, low = -1};
typedef struct t_timeSliceRequest{
unsigned int processId;
unsigned int timeRequired;
int priority;
}timeSliceRequest;
int main(int argc, char *argv[])
{
int socketID = 0 /*Socket Descriptor*/, n = 0;
char recvBuffer[1024];
memset(recvBuffer, '0',sizeof(recvBuffer));
struct sockaddr_in servAddr;
struct t_timeSliceRequest request = { 1,2,high };
if(argc!=2){
fprintf(stderr,"\n Usage: %s <ip of server> \n",argv[0]);
return 1;
}
socketID = socket(AF_INET, SOCK_STREAM, 0);
if(socketID == -1){
fprintf(stderr, "\n Can't create socket \n");
return 1;
}
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(5000);
if(inet_pton(AF_INET, argv[1], &servAddr.sin_addr)==-1){
fprintf(stderr, "\n Unable to convert given IP to Network Form \n inet_pton Error");
return 1;
}
int connectFlag, sendFlag = 0;
connectFlag = connect(socketID, (struct sockaddr *)&servAddr, sizeof(servAddr));
if(connectFlag == -1){
fprintf(stderr, " Connection Failed\n");
return 1;
}
int sin_size = sizeof(struct t_timeSliceRequest);
fprintf(stdout, " \n %d \n %d \n %d", request.processId, request.timeRequired, request.priority);
sendFlag = send(socketID, &request, sin_size ,0);
fprintf(stdout, "\nSend Flag: %d\n", sendFlag);
n = read(socketID, recvBuffer, sizeof(recvBuffer)-1);
recvBuffer[n] = 0;
fprintf(stdout, "%s",recvBuffer);
if(n < 0){
fprintf(stderr, " Read error\n");
}
return 0;
}
This is the full Code, its giving 'Transport endpoint is not connected'
Keep in mind that sending structs like this over the network may lead to interoperability problems:
if source and destination have different endianess, you're going to receive wrong data (consider using functions like htonl to convert the data to network endianess)
you struct needs to be packed, otherwise different compilers can align differently the variables of the struct (see this to get an idea about aligning the variables)
In any case, ENOTCONN suggests an error establishing the connection between the two hosts.
Transport endpoint is not connected error is returned when your socket isn't bound to any (port,address) pair.
If it's a server side, you should use the socket descriptor that is returned by accept call. In case of a client - you should use a socket that is returned by the successful call to connect.
Btw, sending structure the way you are is quite dangerous. Compilers might insert padding bytes between structure members (invisible to you program, but they take space in the structure) to conform some alignment rules for the target platform. Besides, different platforms might have different endianness, which might screw your structure completely. If your client and server are compiled for different machines, the structure layout and endianness can be incompatible. To solve this problem, you can use packed structures. A way of declaring a structure as packed depends on a compiler. For GCC this can be done by means of adding a special attribute to a structure.
Another way to solve this problem is to put each individual field of a structure to a raw byte-buffer manually. The receiving side should take all this data out in exactly the same way as the data was originally put into that buffer. This approach can be tricky, since you need to take into account a network byte order when saving multi-byte values (like int, long etc). There is a special set of functions like htonl, htons, ntohs etc for that.
Updated
In your server:
recvFlag = recv(socketID, &request,sin_size,0);
Here it should be
recvFlag = recv(clientID, &request,sin_size,0);
socketID is a passive socket and can only accept connections (not send any data).
What is more, the result of accept isn't checked for -1.