logo
Thắc mắc về packet của lệnh trong TQTK
dummynai Offline
#1 Đã gửi : 26/04/2012 lúc 02:34:22(UTC)

Danh hiệu: Trứng Gà

Gia nhập: 26-04-2012(UTC)
Bài viết: 10

Cảm ơn: 3 lần
Mình có câu hỏi này nhờ bác GK giúp với.
Số là mình cũng muốn viết cái tool auto một số thao tác trong TQTK (Chỉ là tool hỗ trợ một số tính năng mà mình thấy cần trong khi chơi thôi, chứ ko phải là tool hoành tráng giống auto này). Đã thử ngồi bắt các packet của flash client gửi đi tới server TQTK để phân tích. Theo mình thấy thì 1 packet (1 câu lệnh) gửi đi bao gồm:

  1. Command
  2. UserID
  3. SessionKey
  4. CommandData1
  5. CommandData2
  6. Chuỗi 32 bytes

Chỗ mình chưa biết là cái phần cuối cùng trong packet, chính là phần chuỗi 32bytes đó. Bác GK có thể hướng dẫn giúp mình xem cái chuỗi đó tính toán làm sao được không bác.

Cám ơn bác nhiều.

GiacKhongDaiSu Offline
#2 Đã gửi : 26/04/2012 lúc 02:36:36(UTC)

Danh hiệu: Kê Vương

Gia nhập: 23-01-2011(UTC)
Bài viết: 2,113
Man
Đến từ: HCM

Thanks: 4 times
Được cảm ơn: 300 lần trong 220 bài viết
Originally Posted by: dummynai Go to Quoted Post
Mình có câu hỏi này nhờ bác GK giúp với.
Số là mình cũng muốn viết cái tool auto một số thao tác trong TQTK (Chỉ là tool hỗ trợ một số tính năng mà mình thấy cần trong khi chơi thôi, chứ ko phải là tool hoành tráng giống auto này). Đã thử ngồi bắt các packet của flash client gửi đi tới server TQTK để phân tích. Theo mình thấy thì 1 packet (1 câu lệnh) gửi đi bao gồm:

  1. Command
  2. UserID
  3. SessionKey
  4. CommandData1
  5. CommandData2
  6. Chuỗi 32 bytes

Chỗ mình chưa biết là cái phần cuối cùng trong packet, chính là phần chuỗi 32bytes đó. Bác GK có thể hướng dẫn giúp mình xem cái chuỗi đó tính toán làm sao được không bác.

Cám ơn bác nhiều.



Hì tất cả hướng dẫn về lập trình viết auto mình chỉ hướng dẫn cho thành viên nhóm phát triển của Gà Con Club thôi bạn ạ.

Để trở thảnh thành viên nhóm phát triển bạn phải tham gia Gà Con Club một thời gian, tham gia gặp mặt, off iếc quen biết để tạo tin tưởng hoặc được sự giới thiệu trực tiếp của các thành viên uy tín như: GiacKhong, SuTieu, Anh XiaoFeng,...
dummynai Offline
#3 Đã gửi : 26/04/2012 lúc 02:39:39(UTC)

Danh hiệu: Trứng Gà

Gia nhập: 26-04-2012(UTC)
Bài viết: 10

Cảm ơn: 3 lần
Cám ơn bác đã trả lời, mình lại vọc tiếp thôi vậy.
SuTieu Offline
#4 Đã gửi : 07/05/2012 lúc 11:11:07(UTC)

Danh hiệu: Gà Trưởng Thành

Gia nhập: 18-02-2011(UTC)
Bài viết: 110
Đến từ: SinhCat.,JSC

Cảm ơn: 10 lần
Được cảm ơn: 25 lần trong 22 bài viết
Originally Posted by: dummynai Go to Quoted Post
Cám ơn bác đã trả lời, mình lại vọc tiếp thôi vậy.


Chặng đường gian nan và gần như không có ánh sáng cuối đường hầm.
Hỗ trợ bạn bài viết tham khảo của chiro8x trên hva để hy vọng có ngày mai tươi sáng

Em đang viết chương trình sử dụng thư viện libpcap để gửi và nhận gói tin, công việc suôn sẽ cho tới khi gặp việc tính toán checksum. Vì thiếu hiểu biết nên em đã tính toán sai cơ bản dẫn tới checksum không đúng. Gói tin bị DROP và không có reply từ server mặc dù em không spoof IP. Sau đây em xin được chia sẽ những cái ngu cơ bản của em để lần sau các bạn có tìm hiểu về cái này cũng không tốn kém nhiều thời gian.

Các header em sử dụng:

Code:

#include <stdlib.h>
#include <pcap.h>
#include <sys/types.h>
#include <string.h>

#define __FAVOR_BSD 1;

#include <netinet/ether.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <time.h>



1. Hàm tính checksum.

Cụ thể thế nào các bạn cứ mỗ xẽ nó ra, và nghiền ngẫm. Nó dễ hiểu và không khó với ai có căn bản. Nếu không hiểu các bạn có thể reply bên dưới mình sẽ trả lời.

Code:

uint16_t checksum(const uint16_t* buf, unsigned int nbytes){

uint32_t sum = 0;

for (; nbytes > 1; nbytes -= 2){
sum += *buf++;
}

if (nbytes == 1)
{
sum += *(unsigned char*) buf;
}

sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);

return ~sum;

}



2. Tính checksum cho gói IP.

Check sum gói IP sẽ bao gồm toàn bộ nội dung gói IP. Chúng ta chuyển gói IP bào buffer và gọi hàm checksum để tính toán.

Code:

uint16_t check_ip(iphdr ipheader){
uint16_t *ptr;
uint16_t sum = 0;
size_t ip_s = sizeof(iphdr);
ptr = new uint16_t [ip_s/2];
memcpy(ptr, &ipheader, ip_s);

sum = checksum(ptr, ip_s);
delete ptr;
return sum;

}



3. Tính checksum cho gói ICMP.

Gói ICMP khác với gói IP vì nó có chứa thêm data field lúc trước đã có lần em tính thiểu cái data field kết quả là checksum bị sai, nhưng thêm data field vào vẫn bị sai em cảm thấy bức bách lắm, nhưng để ý kỹ lại sẽ thấy như sau memcpy(ptr + icmp_s, dat, dat_size); bởi vì ptr là con trỏ uint16_t nó là 2 bytes nên dịch nó phải công cho icmp_s/2 nhưng xuống đoạn tính checksum không phải là sum = checksum(ptr, pkt_s/2); mà là sum = checksum(ptr, pkt_s); vì ở đây nó tính bằng bytes nếu tính toán máy móc chút là sẽ sai checksum.

Code:

uint16_t check_icmp(icmphdr icmpheader, char *dat, size_t dat_size){
uint16_t *ptr;
uint16_t sum = 0;

size_t icmp_s = sizeof(icmphdr);
size_t pkt_s = sizeof(iphdr) + icmp_s + dat_size;

if(sizeof(iphdr)%2 == 1 || dat_size%2 == 1)return 0x0000;

ptr = new uint16_t [pkt_s/2];
memcpy(ptr, &icmpheader, icmp_s);
memcpy(ptr + icmp_s/2, dat, dat_size);

sum = checksum(ptr, pkt_s);
delete ptr;
return sum;

}



4. Tính checksum cho gói TCP

Đoạn này thì em mới bộc lộ cái ngu ra, em tính mỗi tcpheader và data, vì ăn quen mà tưởng nó giống như ICMP header. Sau này đọc tài liệu mới biết. Trước đây người ta không phân chia ra TCP hay IP và UDP mà chỉ có TCP kể từ năm 1970 mới tách ra để làm cấu trúc của gói tin minh bạch hơn. Để tính toán checksum cần phải tính cả những thứ "nguyên thuỷ" thuộc về nó pseudo header và cấu trúc của nó đây:

Code:

struct pseudo_header
{
unsigned int s_addr;
unsigned int d_addr;
char reserved;
unsigned char protocol;
unsigned short length;
};



Và đây là mã của tính toàn TCP:

Code:

uint16_t check_tcp_syn(iphdr ipheader, tcp_syn tcpheader, char* opt, size_t opt_size){
uint16_t *ptr;
uint16_t sum = 0;
pseudo_header psdheader;
size_t psd_s = sizeof(pseudo_header);
size_t tcp_s = sizeof(tcp_syn);
size_t pkt_s = psd_s + tcp_s + opt_size;

ptr = new uint16_t [pkt_s/2];

psdheader.s_addr = ipheader.saddr;
psdheader.d_addr = ipheader.daddr;
psdheader.reserved = 0;
psdheader.protocol = ipheader.protocol;
psdheader.length = htons(tcp_s+opt_size);

memcpy(ptr, &psdheader, psd_s);
memcpy(ptr + psd_s/2 , &tcpheader, tcp_s);
memcpy(ptr + psd_s/2 + tcp_s/2, opt, opt_size);
sum = checksum(ptr, pkt_s);

delete ptr;
return sum;

}



Ở trên là gói SYN không có data field em chưa viết phần đó. Để hôm nào phân tích bằng WireShark đã rồi tính tiếp. Nhưng về cơ bản ta sẽ đưa data field vào và tăng length lên thôi. Cái opt là TCP options.

5. Tính toán checksum với gói UDP

Việc tính toán check sum gói tin này sẽ giống với TCP tức là tính cả pseudo header. Dưới đây là mã tính toán nó.

Code:

uint16_t check_udp(iphdr ipheader, udphdr udpheader, char* dat, size_t dat_size){
uint16_t *ptr;
uint16_t sum = 0;
pseudo_header psdheader;
size_t psd_s = sizeof(pseudo_header);
size_t udp_s = sizeof(udphdr);
size_t pkt_s = psd_s + udp_s + dat_size;

ptr = new uint16_t [pkt_s/2];

psdheader.s_addr = ipheader.saddr;
psdheader.d_addr = ipheader.daddr;
psdheader.reserved = 0;
psdheader.protocol = ipheader.protocol;
psdheader.length = htons(udp_s + dat_size);

memcpy(ptr, &psdheader, psd_s);
memcpy(ptr + psd_s/2 , &udpheader, udp_s);
memcpy(ptr + psd_s/2 + udp_s/2, dat, dat_size);

sum = checksum(ptr, pkt_s);
delete ptr;
return sum;
}



6. Kết bài
Viết tới đây chắc cũng có bạn thắc mắc sao đoạn này em rườm rà thế.

Code:

sum = checksum(ptr, pkt_s);
delete ptr;
return sum;



Em làm thế vì nếu return ngay con trỏ ptr sẽ không được giải phóng.

Từng đó thôi cũng đủ làm em tốn mất 2 ngày, đúng là sự thiếu hiểu biết thật đáng sợ. Lần sau em sẽ tìm hiểu một vấn đề kỹ càng hơn trước khi làm và đặt câu hỏi, cảm ơn anh conmale và bạn vd_ đã trả lời những thẳng mắc hồn nhiên của em :">.

P/S: các bạn có thể sử dụng các hàm trên để:
- Thử nghiệm việc gửi nhận các gói tin.
- Viết module tự correct checksum trước khi gửi đi.
- Bắt phân tích các gói checksum bị lỗi.

Mà nguồn trên được em viết bằng C++ có tham khảo thêm các bài viết từ:
http://tcpdump.org/
http://www.winpcap.org/
http://www.cplusplus.com/
http://yuba.stanford.edu...sado/pcap/section1.html

Một số trang khác nữa khi nào nhớ em sẽ bổ sung.
1 người cảm ơn SuTieu cho bài viết.
dummynai trên 08-05-2012(UTC) ngày
dummynai Offline
#5 Đã gửi : 08/05/2012 lúc 07:38:59(UTC)

Danh hiệu: Trứng Gà

Gia nhập: 26-04-2012(UTC)
Bài viết: 10

Cảm ơn: 3 lần
Cám ơn bạn nhé, SuTieu.
Ai đang xem chủ đề này?
Guest (6)
Bạn không thể tạo chủ đề mới trong diễn đàn này.
Bạn không thể trả lời chủ đề trong diễn đàn này.
Bạn không thể xóa bài của bạn trong diễn đàn này.
Bạn không thể sửa bài của bạn trong diễn đàn này.
Bạn không thể tạo bình chọn trong diễn đàn này.
Bạn không thể bỏ phiếu bình chọn trong diễn đàn này.

Green-Grey Theme Created by Ingo Herbote (WatchersNET.de)
Powered by YAF | YAF © 2003-2010, Yet Another Forum.NET
Thời gian xử lý trang này hết 0.281 giây.