14 ms·
Hmm... #define PAYLOADSIZE 0x2000 code += PAYLOADSIZE - 1024; memcpy((void*)code, &kernel_payload, 1024); Does anybody know if it's possible to find out
by smtddr 13y ago
Hmm...
#define PAYLOADSIZE 0x2000
code += PAYLOADSIZE - 1024;
memcpy((void*)code, &kernel_payload, 1024);
Does anybody know if it's possible to find out the size of a function during run time? Could you like say, put a return at the end of the function then do a for-loop with memcpy() for each byte until you run into the OPCODE for RET? I guess I could do a test.
- userbinator 13y agoRET is 195 or C3 in hex which also corresponds to modrm operands "eax, ebx" or "ebx, eax" so there's a pretty good chance of say a MOV instruction e.g. 89 C3, "mov ebx, eax" or something else also having that byte inside it, not to mention constants and offsets. (If you work with x86 asm enough, you will start memorising opcodes...)
- smtddr 13y agoHmm... so after looking at http://ref.x86asm.net/coder32.html http://ref.x86asm.net/coder32.html apparently 0xC2 and 0xC3 are RET. On my 32bit Linux machine, the following code printed "Okay! c2 found @ 174" Is this code correct in any way??? I guess the fact that I'm assuming every byte is a whole instruction; not even accounting for the operands is already a problem. But am I even reading the bytes properly at all? #include <stdio.h> void rightmeow() { int q; for(q = 0; q < 10 ; q++) printf("It's new!\n"); return; } int main(int argc, char** argv) { int i; unsigned char bytecode; for(i = 0; i < 9999 ; i++) { bytecode = (unsigned char)(**(rightmeow+i));//--- does this really work? if (bytecode == 0xC2 || bytecode == 0xC3) break; } if( i == 9999) printf("No good.\n"); else printf("Okay! %x found @ %d\n",bytecode,i); return 0; }
- userbinator 13y agoYou probably mean *(((unsigned char *)rightmeow)+i) but just change the "q < 10" line to "q < 195" and you should see the output change, since that immediate constant is going to be present at least once before the final ret. For me, changing that changes the output from c3 being found at 47 to it being found at 25.
- smtddr 13y agoNice! For me it changed from being found at 38, to 34. I wonder why you get C3 while I get C2.
- userbinator 13y agoC2 is RET iw, i.e. has 16-bit immediate value following the instruction, the # of bytes of parameters to pop from the stack. That should be 0 in this case so it could use C3 and save 2 bytes, but compilers aren't always really intelligent, although this is the first time I've seen that. Then again, it could be something else and not the actual return you found.
- revelation 13y agoOf course, functions commonly have multiple rets, jump tables at the end, etc. I don't think theres a robust way sans symbols.
- userbinator 13y agoIf you know the address of the function that comes immediately after it, then subtract the two. This will include padding nops at the end etc. so it might be slightly bigger than the real size but you won't be missing bytes from the tail, which is what really matters in this application.
- revelation 13y agoHence why I mention symbols, that would have been exactly the way I'd do it. But without symbols, you can't know what the next function is, thats entirely upon the compiler (linker even) to decide.
- userbinator 13y agoUsually they'll be in the same order as they were in the source code.
- deleted 13y ago[deleted]
- aortega 13y agoMaybe it is possible if you don't use any optimizations and always use the same compiler. A function may have the RET in the middle of it. Or use a jmp instead of ret (tail optimization), etc.
- emillon 13y agoAs others said, you can't really do it without disassembling the function (bonus problem: the general case is undecidable). A solution is to have your linker insert a "end of function" symbol in the ELF object (using a linker script), and import it in your C code a pointer. Then the size of f is "f_end - (void\*) f".