1

python:

msg = b'aaa\x01' + b'\x00' + b'\x23\x45cc'
dl = cdll.LoadLibrary
lib = dl("./test.so")
lib.send.argtypes = c_char_p
lib.send(msg)

c (test.so):

void send(char * msg)
{       
        // printf("%s", msg);
        SSL_write(ssl, msg, strlen(msg));
}

how can I pass '\x00' and what's behind it in?

Thanks!

pipik
  • 11
  • 2
  • 1
    You *are* passing it in. But, a hint: How does printf know where the end of the string is? – user253751 Nov 23 '22 at 16:20
  • 2
    [\[SO\]: C function called from Python via ctypes returns incorrect value (@CristiFati's answer)](https://stackoverflow.com/a/58611011/4788546). ***argtypes* should be a sequence**. *c\_char\_p* is for *NUL* terminated strings. If you want *NUL*s in your string, you should use *POINTER(c\_char)* (but you'd also need to pass the length). However *printf* is supposed to work that way (it would be the same behavior if calling it from *C*), so we're having an *XY Problem* here. – CristiFati Nov 23 '22 at 16:21
  • If you want to manipulate a string that might contain `00` bytes, then pretty much by definition you need to find a data structure *other* than a null-terminated string to do it with! In C, at least, the usual way to do that is with a *pair* of arguments: a char pointer, and a length. Can you rearrange your dll setup and calling convention to use that? – Steve Summit Nov 23 '22 at 16:30
  • The other question is, given a char pointer and a length, how do you print it? Obviously `printf("%s")` doesn't cut it. – Steve Summit Nov 23 '22 at 16:31
  • What does this have to do with Python? If you called `send` from C with the same string literal, the same thing would happen. – Joseph Sible-Reinstate Monica Nov 23 '22 at 20:49
  • Sorry for my mistake, I actually wanna call `SSL_write()`, but I will try to use POINTER(c_char), thank you all! – pipik Nov 24 '22 at 01:18

1 Answers1

1

As indicated in comments, printf with %s only prints a char* up to the first null byte found. The C function needs to know the size and some of your bytes are non-printing characters, so printing the bytes in hexadecimal for the specified length is an option:

test.c

#include <stdio.h>
#include <stdlib.h>

#ifdef _WIN32
#   define API __declspec(dllexport)
#else
#   define API
#endif

API void send(const char* msg, size_t size)
{
    for(size_t i = 0; i < size; ++i)
        printf("%02X ", msg[i]);
    printf("\n");
}

test.py

import ctypes as ct

msg = b'aaa\x01\x00\x23\x45cc'
dll = ct.CDLL('./test')
dll.send.argtypes = ct.c_char_p, ct.c_size_t
dll.send.restype = None
dll.send(msg, len(msg))

Output:

61 61 61 01 00 23 45 63 63
Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251