News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

returning pointer to SSL structure from SSL function

Started by cyrus, January 23, 2024, 07:51:34 AM

Previous topic - Next topic

HSE

Equations in Assembly: SmplMath

jj2007

Quote from: cyrus on January 23, 2024, 12:18:52 PMI'm just using OpenSSL.

Would you be so kind and supply a minimum of documentation? I.e. what kind of arguments does "OpenSSL" expect?

Here is an example of what we need to help you:
BOOL CreateProcessA(
  [in, optional]      LPCSTR                lpApplicationName,
  [in, out, optional] LPSTR                 lpCommandLine,
  [in, optional]      LPSECURITY_ATTRIBUTES lpProcessAttributes,
  [in, optional]      LPSECURITY_ATTRIBUTES lpThreadAttributes,
  [in]                BOOL                  bInheritHandles,
  [in]                DWORD                 dwCreationFlags,
  [in, optional]      LPVOID                lpEnvironment,
  [in, optional]      LPCSTR                lpCurrentDirectory,
  [in]                LPSTARTUPINFOA        lpStartupInfo,
  [out]               LPPROCESS_INFORMATION lpProcessInformation
);

NoCforMe

Assembly language programming should be fun. That's why I do it.

cyrus

Quote from: NoCforMe on January 23, 2024, 12:12:19 PMOK, here's (hopefully) a little more help. I've converted that structure for you. Here it is. It took me all of 10 minutes to do it.

SSL_METHOD    STRUCT
  version            DQ ?
  flags            DQ ?
  mmask            DQ ?
  Pssl_new        DQ ?
  Pssl_free        DQ ?
  Pssl_reset        DQ ?
  Pssl_init        DQ ?
  Pssl_clear        DQ ?
  Pssl_deinit        DQ ?
  Pssl_accept        DQ ?
  Pssl_connect        DQ ?
  Pssl_read        DQ ?
  Pssl_peek        DQ ?
  Pssl_write        DQ ?
  Pssl_shutdown        DQ ?
  Pssl_renegotiate        DQ ?
  Pssl_renegotiate_check    DQ ?
  Pssl_read_bytes        DQ ?
  Pssl_write_bytes        DQ ?
  Pssl_dispatch_alert    DQ ?
  Pssl_ctrl        DQ ?
  Pssl_ctx_ctrl        DQ ?
  PPget_cipher_by_char    DQ ?
  Pput_cipher_by_char    DQ ?
  Pssl_pending        DQ ?
  Pnum_ciphers        DQ ?
  PPget_cipher        DQ ?
  Pget_timeout        DQ ?
  Pssl3_enc        DQ ?
  Pssl_version        DQ ?
  Pssl_callback_ctrl    DQ ?
  Pssl_ctx_callback_ctr    DQ ?
SSL_METHOD    ENDS

Members starting with "P" are pointers; those starting with "PP" are pointers to pointers.

This should at least get you started; I believe if you define this structure (put this code at the top of your program) AND declare and instance of this structure

MySSLmethod      SSL_METHOD <>

then at least the function call should succeed.

What the hell to do with the contents of the structure once you get it, I have no idea. You apparently have to use all those pointers to functions (or "methods" to use the fancy-schmancy C++ lingo) to call them, and I have no idea how to do that. Probably something like this, to take one member as an example:

    int (*ssl_clear) (SSL *s);

    INVOKE Pssl_clear, s        ;where "s" is a pointer to an SSL, whatever that is

; or if you don't use INVOKE, use good old "push-push-call":

    PUSH    s
    CALL    <struct name>.Pssl_clear


Ok thanks a lot for putting that together. Here is what I've done after declaring the struct as you just did. I declared method as a pointer to that struct

method  DQ MySSLmethod

Then here is how my code looks:

call TLS_client_method
mov method, rax

mov rcx, qword ptr [method]
sub rsp, 20h
call SSL_CTX_new
mov SSL_CTX, rax

It fails. I also tried lea rcx, method but fails too. I get the same error.

NoCforMe

Sorry, can't help you with that level of detail. Wish I could. But some general questions and observations:

First of all, why are you trying to use assembly language here? Do you want to, or do you have to? Not trying to talk you out of it, just wondering the reason why.

About all this object stuff:
There seems to be a lot of mystery surrounding the whole idea of "objects" and "methods", which may make one believe that they're totally impenetrable concepts that can't be used in assembly language.

My guess©® is that this is just not true. Those "objects" and "methods" ultimately have to be just plain functions and data objects, which can be expressed in an assembly-language program. Of course, you have to know what the functions do, what arguments the functions expect, what results they return, and the format of any structures. And of course you need the functions themselves, either in a static library or a DLL. But if you know all that, I don't see why you can't write an assembly-language program which replicates exactly the C++ equivalent code. And without having to use an "object-oriented assembler".

Not saying it would be easy. But it should be possible.

Let's take one example. In the ssl_method_st structure, let's say you want to invoke the "method" ssl_read (in other words, call that function): this can be accomplished thus, using "push-push-call" (minus any needed stack manipulation, which I'm not familiar with but you seem to be):
;    int (*ssl_read) (SSL *s, void *buf, size_t len, size_t *readbytes);

    PUSH    Preadbytes
    PUSH    len
    PUSH    Pbuf
    PUSH    Ps
    CALL    MySSLmethod.ssl_read

(This may be wrong, as I don't know the X64 ABI; maybe some of those arguments have to go into registers instead. But you get the idea.)

All those scary-looking members are just pointers to functions. That's all. You set up the parameters and call them.

If anything I'm writing here is wrong, I'd appreciate being corrected. I really don't want to mislead you.

On second thought, may be I can help you. You're trying to call a function of type SSL_CTX, right? But you don't call the type; you call the function itself through its pointer, which is part of that stucture:
;    SSL *(*ssl_new) (SSL_CTX *ctx);

    MOV    RCX, Pctx
    SUB    RSP, 20h
    CALL   MySSLmethod.Pssl_new
    MOV    result, RAX
assuming that Pctx is a pointer to a thing of type SSL_CTX, and result is a thing of type SSL.

Aargh; unless you have to dereference that pointer, since it's a pointer to a pointer (*(*ssl_new)), in which case you'd need something like
    MOV    RAX, MySSLmethod.Pssl_new
    MOV    RAX, [RAX]
    CALL   RAX
    ...
But this is just a guess on my part. Others may be able to figure this out ...

Maybe try this? Do you see what's going on here?
Assembly language programming should be fun. That's why I do it.

cyrus

Quote from: NoCforMe on January 23, 2024, 01:13:22 PMSorry, can't help you with that level of detail. Wish I could. But some general questions and observations:

First of all, why are you trying to use assembly language here? Do you want to, or do you have to? Not trying to talk you out of it, just wondering the reason why.

About all this object stuff:
There seems to be a lot of mystery surrounding the whole idea of "objects" and "methods", which may make one believe that they're totally impenetrable concepts that can't be used in assembly language.

My guess©® is that this is just not true. Those "objects" and "methods" ultimately have to be just plain functions and data objects, which can be expressed in an assembly-language program. Of course, you have to know what the functions do, what arguments the functions expect, what results they return, and the format of any structures. And of course you need the functions themselves, either in a static library or a DLL. But if you know all that, I don't see why you can't write an assembly-language program which replicates exactly the C++ equivalent code. And without having to use an "object-oriented assembler".

Not saying it would be easy. But it should be possible.

Let's take one example. In the ssl_method_st structure, let's say you want to invoke the "method" ssl_read (in other words, call that function): this can be accomplished thus, using "push-push-call" (minus any needed stack manipulation, which I'm not familiar with but you seem to be):
;    int (*ssl_read) (SSL *s, void *buf, size_t len, size_t *readbytes);

    PUSH    Preadbytes
    PUSH    len
    PUSH    Pbuf
    PUSH    Ps
    CALL    MySSLmethod.ssl_read

(This may be wrong, as I don't know the X64 ABI; maybe some of those arguments have to go into registers instead. But you get the idea.)

All those scary-looking members are just pointers to functions. That's all. You set up the parameters and call them.

If anything I'm writing here is wrong, I'd appreciate being corrected. I really don't want to mislead you.

On second thought, may be I can help you. You're trying to call a function of type SSL_CTX, right? But you don't call the type; you call the function itself through its pointer, which is part of that stucture:
;    SSL *(*ssl_new) (SSL_CTX *ctx);

    MOV    RCX, Pctx
    SUB    RSP, 20h
    CALL   MySSLmethod.Pssl_new
    MOV    result, RAX
assuming that Pctx is a pointer to a thing of type SSL_CTX, and result is a thing of type SSL.

Aargh; unless you have to dereference that pointer, since it's a pointer to a pointer (*(*ssl_new)), in which case you'd need something like
    MOV    RAX, MySSLmethod.Pssl_new
    MOV    RAX, [RAX]
    CALL   RAX
    ...
But this is just a guess on my part. Others may be able to figure this out ...

Maybe try this? Do you see what's going on here?

I'm writing a simple SSL client basically. Yeah I believe I would have to rip through that entire SSL code and get just the nitty gritty functions that I want to use and rewrite them. Yes it would be difficult because I've done something similar. Took me 3 months to read the all functions needed lol. All their scary looking contexts boiled down to basically a handful of functions that I just re-wrote and 2 of them were actually assembly routines that I ended up including and calling from the kernel itself. It was kind of funny after reading thousands of lines of code, all I ever needed was a couple lines of code.

I do know how those ugly function pointers work lol. The ones with returning a pointer to a struct looks pretty hairy. I remember going through these in 2015 in King's book on C. He explained it very well. Yep definitely know how to call them in assembly too, you are correct. As you stated, though, those objects all boil down to just some function call anyway, nothing special about them.


NoCforMe

Regarding that last part I wrote, I think I misread that structure member.

SSL *(*ssl_new) (SSL_CTX *ctx) means that the member is a pointer to a function (*ssl_new) that returns a pointer to an SSL, so no de-referencing needed (it's not a pointer to a pointer).

I think.
Assembly language programming should be fun. That's why I do it.

cyrus

Quote from: NoCforMe on January 23, 2024, 03:13:18 PMRegarding that last part I wrote, I think I misread that structure member.

SSL *(*ssl_new) (SSL_CTX *ctx) means that the member is a pointer to a function (*ssl_new) that returns a pointer to an SSL, so no de-referencing needed (it's not a pointer to a pointer).

I think.


lol yes you're right. Actually that function pointer is exactly the final command I listed in my original post.

SSL *ssl = SSL_new (ctx);

TimoVJL

SSL_METHOD_ST    128 80h bytes
version          +0h 4h
flags            +4h 4h
mask            +8h 4h
ssl_new          +Ch 4h

x64

SSL_METHOD_ST    248 F8h bytes
version          +0h 4h
flags            +4h 4h
mask            +8h 4h
ssl_new          +10h 8h
May the source be with you

NoCforMe

Quote from: TimoVJL on January 23, 2024, 05:06:38 PMx64

SSL_METHOD_ST    248 F8h bytes
Hmm; I counted 36 members, each 8 bytes I'm assuming (X64), for a total of 288 bytes. ?????
Assembly language programming should be fun. That's why I do it.

NoCforMe

OP: Hate to put flies in the ointment, but why is your structure different from this one? This one (and numerous others I found online) doesn't have the flags or mask members.
Assembly language programming should be fun. That's why I do it.

TimoVJL

#26
I just took  it from

https://masm32.com/board/index.php?msg=126423

Another version:
SSL_METHOD      120 78h bytes
version          +0h 4h
ssl_new          +4h 4h

SSL_METHOD      240 F0h bytes
version          +0h 4h
ssl_new          +8h 8h

  408 /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
  409 struct ssl_method_st
  410     {
  411     int version;
  412     int (*ssl_new)(SSL *s);
  413     void (*ssl_clear)(SSL *s);
  414     void (*ssl_free)(SSL *s);
  415     int (*ssl_accept)(SSL *s);
  416     int (*ssl_connect)(SSL *s);
  417     int (*ssl_read)(SSL *s,void *buf,int len);
  418     int (*ssl_peek)(SSL *s,void *buf,int len);
  419     int (*ssl_write)(SSL *s,const void *buf,int len);
  420     int (*ssl_shutdown)(SSL *s);
  421     int (*ssl_renegotiate)(SSL *s);
  422     int (*ssl_renegotiate_check)(SSL *s);
  423     long (*ssl_get_message)(SSL *s, int st1, int stn, int mt, long
  424         max, int *ok);
  425     int (*ssl_read_bytes)(SSL *s, int type, unsigned char *buf, int len,
  426         int peek);
  427     int (*ssl_write_bytes)(SSL *s, int type, const void *buf_, int len);
  428     int (*ssl_dispatch_alert)(SSL *s);
  429     long (*ssl_ctrl)(SSL *s,int cmd,long larg,void *parg);
  430     long (*ssl_ctx_ctrl)(SSL_CTX *ctx,int cmd,long larg,void *parg);
  431     const SSL_CIPHER *(*get_cipher_by_char)(const unsigned char *ptr);
  432     int (*put_cipher_by_char)(const SSL_CIPHER *cipher,unsigned char *ptr);
  433     int (*ssl_pending)(const SSL *s);
  434     int (*num_ciphers)(void);
  435     const SSL_CIPHER *(*get_cipher)(unsigned ncipher);
  436     const struct ssl_method_st *(*get_ssl_method)(int version);
  437     long (*get_timeout)(void);
  438     struct ssl3_enc_method *ssl3_enc; /* Extra SSLv3/TLS stuff */
  439     int (*ssl_version)(void);
  440     long (*ssl_callback_ctrl)(SSL *s, int cb_id, void (*fp)(void));
  441     long (*ssl_ctx_callback_ctrl)(SSL_CTX *s, int cb_id, void (*fp)(void));
  442     };
 
May the source be with you

NoCforMe

Assembly language programming should be fun. That's why I do it.

jj2007

Quote from: NoCforMe on January 23, 2024, 01:13:22 PMThere seems to be a lot of mystery surrounding the whole idea of "objects" and "methods", which may make one believe that they're totally impenetrable concepts that can't be used in assembly language.

Basically,
- you call some InitMyObject(pToObject) API;
- eax signals whether your call was successful (S_OK) or not;
- if successful, pToObject points to n bytes of memory;
- this memory is structured, i.e. you can access its bytes as
  mov esi, pToObject
  myObj equ [esi.NAMEOFSTRUCT]  ; an equate to avoid [esi.NAMEOFSTRUCT].someMethod
  a) mov eax, myObj.colorOfObject
  b) push Rgb(255, 128, 0) & call myObj.changeColorMethod

That's all, mystery solved :cool:

_japheth

Converting C structures to assembly isn't always trivial.

SSL_METHOD    STRUCT
  version            DQ ?
  flags            DQ ?
  mmask            DQ ?
  Pssl_new        DQ ?
  Pssl_free        DQ ?
  Pssl_reset        DQ ?
  Pssl_init        DQ ?
 <snip>
  Pssl_ctx_callback_ctr    DQ ?
SSL_METHOD    ENDS

There are errors in this definition. In 64-bit C(++) for Windows, an "int" is still 32-bit, and, IIRC, a long as well ( to define a 64-bit integer, one has to use "long long" or "__int64 int" ).
So this struct probably should rather look like this:

SSL_METHOD    STRUCT 8
  version            DD ?
  flags            DD ?
  mmask            DD ?
  Pssl_new        DQ ?
  Pssl_free        DQ ?
  Pssl_reset        DQ ?
  Pssl_init        DQ ?
 <snip>
  Pssl_ctx_callback_ctr    DQ ?
SSL_METHOD    ENDS

Don't miss the "8" behind "STRUCT" - structure alignment MUST be 8 to ensure that all Qwords start at an "8-byte boundary".
Dummheit, gepaart mit Dreistigkeit - eine furchtbare Macht.