0

first of all, I know if I was writing pure assembly, I could (and would..) simply write the strings in the .data section or similar. However, in my use-case, that is not an option.

I am using python, and the keystone framework, so no .data section. The task is to execute CreateFile (Windows assembly). How in the world do you make a string like "C:\mine.exe" and put it into RCX??

I have tried qword...I've tried pushing 3 separate values onto the stack and then pointing the stack to rcx. Any direction I can get would be helpful. rax holds the address of CreateFileA (well, its stub in kernel32.dll anyway). RCX = 1.tx (trying to be simple...just something small as a test.

    "   mov     QWORD PTR [rsp+48], 0 ;"
    "   mov     DWORD PTR [rsp+40], 128             ;"
    "   mov     DWORD PTR [rsp+32], 2 ;"
    "   xor     r9d, r9d ;"
    "   xor     r8d, r8d ;"
    "   mov     edx, 1073741824                     ;"
    "   mov rcx, 0x00000000312e7479 ;"
    "   int3                        ;"
    "   call    rax ;"
    "   mov     QWORD PTR hFile$[rsp], rax ;"

The below code shows another method, in which I store the values on the stack, then try and point rsp to rcx.

    "   mov     QWORD PTR [rsp+48], 0 ;"
    "   mov     DWORD PTR [rsp+40], 128             ;"
    "   mov     DWORD PTR [rsp+32], 2 ;"
    "   xor     r9d, r9d ;"
    "   xor     r8d, r8d ;"
    "   mov     edx, 1073741824                     ;"
    "   push 2e747874h ;"
    "   push 5c746573h ;"
    "   push 656e7473h ;"
    "   push 6f63756dh ;"
    "   push 696e5c44h ;"
    "   push 5c61646dh ;"
    "   push 73657273h ;"
    "   push 433a5c55h ;"
    "   int3                        ;"
    "   mov rcx, rsp                ;"
    "   call    rax ;"
    "   mov     QWORD PTR hFile$[rsp], rax ;"
raithedavion
  • 127
  • 1
  • 12
  • See [Create an arg array for execve on the stack](//stackoverflow.com/q/59825101) for an example, and some comments. You can simply store to stack space with mov dword immediate, or mov a qword to a register and push or store that. Or `push sign_extended_imm32` and then use a dword store to fill the 4 bytes. There are tons of ways to construct 0-terminated strings on the stack. – Peter Cordes Feb 04 '20 at 05:27
  • Those methods do not seem to work on the Windows side, at least not in the context of keystone-engine and python. When I go to debug, the mov qword isn't even there (keystone-engine throws it out due to something being invalid). Going to keep trying. But any further assistance would be appreciated. – raithedavion Feb 04 '20 at 06:07
  • 1
    What, the `mov QWORD PTR [rsp+48], 0` in your code isn't present when when you disassemble? x86-64 machine code runs the same regardless of OS; methods for constructing small arrays on the stack don't depend on the OS. You need to know the right syntax for your assembler, in this case keystone? I don't know it but it looks like GNU `.intel_syntax noprefix` which is MASM-like. I think the question I linked used NASM syntax so of course you can't copy the instructions exactly, and the calling convention for the system call / WinAPI function is different, too, of course. – Peter Cordes Feb 04 '20 at 06:19
  • It is finding the CreateFileA for the windows api just fine. The mov qwrod ptr [rsp+480, 0 is there. What isn't (and hasn't worked) is the string that for the file name (rcx). – raithedavion Feb 04 '20 at 06:31
  • You do a `mov rcx, rsp` but you haven't stored anything to `[rsp+0]`. Also, don't forget that the callee "owns" its shadow space from RSP+0 to RSP+31 before a call (32 bytes above the return address) so you should put your string somewhere else. (LEA a pointer into RCX, not `mov rcx,rsp`). Test your code in a debugger to make sure RCX is pointing to a string before you port it to keystone. Also, IDK what you're doing with `mov rcx, 0x00000000312e7479` which you overwrite with `rsp` right after the `int3` breakpoint. – Peter Cordes Feb 04 '20 at 06:35
  • Ya, that was a typo from the times I was pushing to rsp then trying to get it into rcx as required.Its my code so I'm the "callee", so I'm not sure that is a big problem. – raithedavion Feb 04 '20 at 06:39
  • Ok, now your code makes no sense. You set RCX to some random integer, not a pointer to a string. Is that hex constant the ASCII bytes you want? It needs to be in memory *pointed to* by RCX. And BTW, the callee I'm talking about is `CreateFileA` - you call it with `call rax`. – Peter Cordes Feb 04 '20 at 06:56
  • Like I said, I have tried everything :). The original thought was push the filename into the stack in reverse order, then point rcx to it. That wasn't working. So I tried this method. – raithedavion Feb 04 '20 at 06:59
  • It would probably be better to show an attempt at passing a pointer in your question so people could see that you're at least trying to do something viable, and spot your mistake. This doesn't show what part of storing to the stack you're confused about, just that you're not even trying to do something that could work. – Peter Cordes Feb 04 '20 at 07:04
  • I added an example where I push the file path/name to the stack, the point rcx at it. That didn't work either. – raithedavion Feb 04 '20 at 13:50
  • 2 problems: you forgot to `sub rsp, 32` after setting RCX to point at what you pushed, so the callee could step on it before reading it. And (as explained in [Create an arg array for execve on the stack](//stackoverflow.com/q/59825101) which I linked earlier) `push` in x86-64 pushes 8 bytes. So you're leaving gaps of 4 bytes of zeros between every chunk of data. So it's almost a duplicate of that Q&A. A good way to do it is `mov r64, imm64` then push the register, for larger strings. – Peter Cordes Feb 04 '20 at 13:57
  • So I'm understanding, do the mov r64, imm64 then right after that doe the push of 8 bytes? Rinse repeat? – raithedavion Feb 04 '20 at 14:12
  • Yes, that's what I said, and yes that will obviously put 8 bytes of contiguous data on the stack. – Peter Cordes Feb 04 '20 at 14:13
  • ``` " sub rsp, 32 ;" " mov r64, imm64;" " push 2e747874h ;" " mov r64, imm64;" " push 5c746573h ;" " mov r64, imm64;" " push 656e7473h ;" " mov r64, imm64;" " push 6f63756dh ;"``` It did not like that in keystone. – raithedavion Feb 04 '20 at 14:19
  • Well, I ended up storing it in a register using offsets. Pure assembly is so much easier. If you want, put in an answer and I'll mark it. @Peter – raithedavion Feb 04 '20 at 15:46
  • `mov r64,imm64` is the generic form of the instruction I was talking about: mov-immediate with a 64-bit immediate. It's not something you literally write, and it's not a modifier for a push-immediate! I meant like `mov rcx, 'abcdefgh'; push rcx` – Peter Cordes Feb 05 '20 at 01:32
  • Ah. I've never done x64 assembly or shellcode before. – raithedavion Feb 05 '20 at 02:12
  • That's how Intel's manuals talk about different forms of instructions, e.g. https://www.felixcloutier.com/x86/mov is an HTML extract. `mov` is the only instruction that can take a 64-bit immediate. – Peter Cordes Feb 05 '20 at 02:16

0 Answers0