Home Frida TCP Hooking
Post
Cancel

Frida TCP Hooking

TCP 통신을 MITM Relay가 아닌 Frida 후킹을 통해 패킷을 잡아봅시다.


개요

소켓 통신에서 C/C++ 함수를 이용하는 방법은 데이터 송수신 함수를 이용하는 방법입니다.

  1. send(), recv()
  2. sendto(), rectfrom()

함수 원형

함수 원형은 아래와 같습니다.

  • send(int sockfd, const void *buf, size_t len, int flags)
  • recv(int sockfd, const void *buf, size_t len, int flags)
  • sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)
  • recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr

*src_addr, socklen_t addrlen)


Send / sendto hooking

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var sendPtr = Module.findExportByName(null, "send/sendto"); 
 //console.log('send address: ' + sendPtr.toString());

 console.log('>> Hooking send() <<'); 
 Interceptor.attach(sendPtr, {
     onEnter: function (args) {
        var send = Memory.readUtf8String(args[1]);
        var changeSend = Memory.allocUtf8String('원하는 변조 값');
        if(send.indexOf('원하는 패킷')>-1)
        {
           console.warn("[*]send buf : " + send);
           console.log("패킷 사이즈 : " + args[2]); //16진수
           args[2] = ptr(53); // 원하는 패킷 사이즈로 변경 10진수
           this.changeSend = changeSend;
           args[1] = changeSend;
           console.warn("[*]send After buf : " + Memory.readUtf8String(args[1]));
           console.log("패킷 사이즈 : " + args[2]);
        }

        //Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\\n")
         }, 
     onLeave: function(retval) {
       
     }});

recv / recvfrom hooking

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var recvPtr = Module.findExportByName("libnative-lib.so", "recv/recvfrom"); 
     //console.log('recv address: ' + recvPtr.toString()); 
     console.log('>> Hooking recv() <<'); 
     Interceptor.attach(recvPtr, {
         onEnter: function (args) {
               var recv = Memory.readCString(args[1]);
               //console.log(recv);
               if(recv.indexOf('result')>-1){
                  console.warn(recv);
               }
         }, 
         onLeave: function (retval) {
             
         }});

후기

처음에는 Memory.writeUtf8Stirng 함수를 이용하여 패킷을 변조했더니 에러가 발생했다. 메모리 권한이 없거나, 패킷 간의 사이즈가 맞지 않아 에러가 발생한것으로 판단하여 → allocUtf8Stirng을 사용하여 메모리 내에 변조 시킬 패킷을 할당 시켰지만 똑같은 에러가 발생하였다…

에러를 찾기 위해 기존 패킷과 변조 패킷의 차이점을 찾기 위해 tcpdump를 이용하여 패킷 분석을 했는데 둘다 0x32 바이트만큼 데이터 부분만 전송 된 것이다. 즉 test → admin 으로 변조를 가정한다면 test → admi 까지만 변수가 입력된다는 것이다.

변수의 크기만큼 할당을 하기 위해 다시 sendto 함수의 원형을 통해 args[2] 변수에 패킷의 크기만큼 저장되는 것을 알아내 내가 원하는 변수의 크기만큼 사이즈를 재할당 했다.