27 Şubat 2016 Cumartesi

Timer

.Net
Windows'ta sistem saati elle değiştirilince, kurulu bekleyen timer'lar kendilerini yeniden kurmazlar. Dolayısıyla karışıklıklar olabilir. Durumu düzeltmek için SystemEvents.TimeChanged event'i dinlenerek timer'ları tekrar kurmak gerekebilir.

System.Windows.Forms.Timer
Konuyu Timer Sınıfları yazısına taşıdım.

System.Timers.Timer
Konuyu Timer Sınıfları yazısına taşıdım.

System.Threading.Timer
Konuyu Timer Sınıfları yazısına taşıdım.

Java
Konuyu Java Timer Sınıfları yazısına taşıdım.

QT
QTimer aslında sadece her QObject sınfının sahip olduğu QObject::startTimer yeteneğini daha rahat kullanmamızı sağlayan bir sınıf. Timers başlıklı QT dokümantasyonunu okumakta fayda var.

POSIX
Posix ile timer yaratmak için bir kaç yöntem var.

alarm() yöntemi
alarm kullanırsak tek thread'li bir timer elde ederiz. Alarmı her seferinden tekrar kurmak gerekir. Örnek'te 3 defa 1 saniye aralıkla çalan bir alarm var.

timer_create yöntemi
timer_create(), timer_settime(),timer_connet(),timer_delete() beraber kullanılıyorlar.İlki timer nesnesini yaratır, ikincisi başlatır, sonuncusu ise timer nesnesini kapatır.

timer_create() metodunun imzası aşağıda.
int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid);
Bu metod ile kullanılan timer_t çoğu derleyicide void * olarak tanımlı. Bu yüzden timer_delete() ile silinmesi gerekiyor.
typedef void * __timer_t;
typedef __timer_t timer_t;

timer_create metodu signal'ler ile beraber kullanılabilir veya kullanılmayabilir.

signal olmadan kullanımı
timer_connect() metodu POSIX'te yok. Bu yöntem vxWorks'te işe yarıyor.
sigevent alanına NULL geçiyoruz. Çağırılacak metod timer_connect() ile belirtiliyor. Örnek:
timer_t polltimerID;
struct itimerspec poll_time;
poll_time.it_value.tv_sec = 0;
poll_time.it_value.tv_nsec= 1000; 

poll_time.it_interval.tv_sec = 0;
poll_time.it_interval.tv_nsec= 1000; // execute it every 1us

if(timer_create (CLOCK_REALTIME, NULL, &polltimerID))
    printf("problem in timer_create(): %s",strerror(errno));

if(timer_connect (polltimerID,MyPollFunction,0))
    printf("problem in timer_connect(): %s",strerror(errno));

if(timer_settime (polltimerID, 0, &poll_time, NULL))
    printf("problem in timer_settime(): %s",strerror(errno));

signal ile kullanımı

timer_create metodunu SIGEV_SIGNAL ile kullanırsak tek thread'li bir timer elde ederiz. Eğer SIGEV_THREAD ile kullanırsak timer'ın her çalışmasında yeni bir thread içinde çalışmasını sağlarız.

setitimer
Şu satırı dahil ederiz.
#include <sys/time.h>
Bu metod eski. timer_settime kullanılmalı. Kabaca şöyle yaparız.
#include <sys/time.h>
#include <signal.h>

void alarmhandler(){
    printf("\nTimer triggered");
}

void main(){
    struct itimerval timerval;
    signal(SIGALRM, alarmhandler);
    timerval.it_value.tv_sec = 1;
    timerval.it_value.tv_usec = 0;
    timerval.it_interval.tv_sec = 30;
    timerval.it_interval.tv_usec = 0;
    setitimer(ITIMER_REAL, &timerval, 0);
    pause();    
}
Çağrı hata varsa -1 döner. Virtual timer olarak ta kullanılabilir. Bu timer sadece uygulama çalışırken etkindir.
setitimer(ITIMER_VIRTUAL, &timerval, NULL);
getitimer ile kalan değer alınabilir.
getitimer(ITIMER_VIRTUAL, &timerval);
timer_settime
Bu metod timer_create ile yaratılmış bir timer'ı başlatır. Başlatmadan önce delay ve interval atanması gerekir. Bu işi yapmak için aşağıdaki gibi bir metod kullanılabilir. Örnek:

void itimerspec(struct itimerspec *tsp, int seconds){
    tsp->it_value.tv_sec = seconds;
    tsp->it_value.tv_nsec = 0;
    tsp->it_interval.tv_sec = seconds;
    tsp->it_interval.tv_nsec = 0;
}

Periodic Timer - SIGEV_THREAD ile
//Thread function to be invoked when the periodic timer expires
void timeoutHandler(sigval_t info)
{
}

struct sigevent sev;
memset(&sev,0,sizeof(struct sigevent));
//notify via thread
sev.sigev_notify = SIGEV_THREAD;
sev.sigev_notify_function = timeoutHandler;
sev.sigev_notify_attributes = NULL;
sev.sigev_value.sival_int =20;
sev.sigev_value.sival_ptr = &timer1;//Allows handler to get ID of this timer
// Create timer based on the current system time (CLOCK_REALTIME)
timer_t timer1;
if (timer_create(CLOCK_REALTIME, &sev, &timer1) != 0)
{
    //Error
}

struct itimerspec ts;
//Set delay
ts.it_value.tv_sec =1;//Delay 1 second
ts.it_value.tv_nsec = 0;
//Set interval
ts.it_interval.tv_sec = 0;
ts.it_interval.tv_nsec = 100000000;//Expire every 10th of a second

if (-1 ==timer_settime(timer1,0,&ts,NULL))
{
    //Error
}
//2 saniye bekle
sleep(2);
//Timer'ı kapatmak için
timer_delete(timer1);

Absolute Timer - SIGEV_SIGNAL ile
Absolute timer, gelecekteki bir zamanda çalışmasını istediğimiz timer anlamına geliyor.Örneği buradan aldım

//Signal handler function to be invoked when the absolute timer expires
void sig_handler (int val)
{
    printf("The timer expired and has entered signal handler: Value: %d\n", val);
}
int main()
{
    int Ret;

    struct sigevent sig;
    sig.sigev_notify = SIGEV_SIGNAL;
    sig.sigev_signo = SIGUSR1;
    signal(SIGUSR1, sig_handler);
   
    //create a new timer.
    timer_t timerid; //Stores the ID of the timer
    Ret = timer_create(CLOCK_REALTIME, &sig, &timerid);
    if (Ret == 0)
    {
        struct timespec newtime; //Stores the current system time
        struct itimerspec in, out; //Input values for the timer
        memset(&newtime, 0, sizeof (struct timespec));
        clock_gettime(CLOCK_REALTIME, &newtime);
        in.it_value.tv_sec = newtime.tv_sec + 10;
        in.it_value.tv_nsec = 0;
        in.it_interval.tv_sec = 0;
        in.it_interval.tv_nsec = 0;
       
        //issue the absolute timer request here.
        Ret = timer_settime(timerid, 1, &in, &out);
        if(Ret == 0)
            sleep(11);
        else
            printf("timer_settime() failed with %d\n", errno);
        //delete the timer.
        timer_delete(timerid);
    }
    else
        printf("timer_create() failed with %d\n", errno);
    return Ret;
}
Win32
WIN32 Timer'ları yazısına taşıdım.

Linux
prctl
Bu metod ile timerların gruplanması kontrol ediliyor. Gecikmeyi azaltmak için aşağıdaki gibi yapılabilir.
prctl(PR_SET_TIMERSLACK, 1);

timerfd_settime
Bu metod ile select veya poll ile dinlenebilen bir timer yaratılabilir. Örnek:

//create timer
int timer_fd  =  timerfd_create(CLOCK_MONOTONIC , 0); //non-settable clock or
int timer_fd  =  timerfd_create(CLOCK_REALTIME, 0); //settable system-wide clock

//periodic timer
struct itimerspec time_period = {{10,0},{10,0}};
result = timerfd_settime(timer_fd, 0, &time_period, NULL);
Bir başka periodic timer örneği:
int timerfd = timerfd_create(CLOCK_MONOTONIC,0);
struct itimerspec timspec;
bzero(&timspec, sizeof(timspec));
timspec.it_interval.tv_sec = 0;
timspec.it_interval.tv_nsec = nanosecondInterval;
timspec.it_value.tv_sec = 0;
timspec.it_value.tv_nsec = 1;

timerfd_settime(timerfd, 0, &timspec, 0);

//absolute timer
struct itimerspec new_value;
struct timespec now;
clock_gettime(CLOCK_REALTIME, &now);
new_value.it_value.tv_sec = now.tv_sec + 10;//expire after 10 seconds
new_value.it_interval.tv_sec = 0;//interval
new_value.it_value.tv_nsec = now.tv_nsec;
          
timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL);

//select or read fd now
//...

High Resolution Timer
Buradaki örnekte hrtimer_init(), hrtimer_start() metodları gösterilmiş.

Kendi Timer Sınıfımız
Buradaki soruda kendi timer sınıfımızı yazmak istersek, ne yapabileceğimiz kabaca anlatılmış.

Tek thread'li gömülü bir yazılım yapıyorsak timer'ı çalıştıran kod öncelik olarak döngüde en başta bir yerde olmalı.

Bir diğer örnekte ise Timer Wheel yapısı anlatılmış.

Timer ve Dictionary
Bazen bir nesne için bayatlama timer'ı tutmak gerekir. Nesnenin anahtar alanı ile timer'ı eşleştiren bir Dictionary yaratılır. Nesne güncellendikçe Dictionary'den Timer bulunur ve tekrar kurulur. Nesne silinmek istenirse önce Timer nesnesi daha sonra nesne silinir.

TimeoutHandler çağrıldığı zaman nesnenin anahtar değerini de veriyor olması gerekir.




21 Şubat 2016 Pazar

Hard ve Soft Link

Hard Link ve Soft Link'in Farkı Nedir?
Soft link silinirse gerçek dosya silinmez.

Hard link aynı dosya sistemi üzerinde oluşturulur! Soft link ise farklı dosya sistemindeki bir dosya için oluşturulabilir.

Kabuktan Hard Link Oluşturma
Windows
mklink komutu ile yapılıyor
mklink /H new.file original.file

Linux
ln komutu ile yapılıyor. Windows'takinin tersi gibi düşünülebilir. Önce mevcut dosya sonra yeni dosya yazılır.
ln original.file new.file

API Kullanarak Hard Link Oluşturma
POSIX
 int link (const char *oldname, const char *newname);
Dosyaya Hard Link Sayısını Öğrenme
Posix
Şöyle yaparız.
struct stat st;

if (stat(".."", &st) != -1) 
  printf("%d hard links\n", st.st_nlink);

Java
Hard link sayısının hakkında bilgi almak için Linux Dosya Distemi başlıklı yazıya göz atabilirsiniz.
Files.getAttribute metodu ile bilgiye erişmek mümkün.
java.nio.file.Files.getAttribute(path, "unix:nlink")

--------------------------------------------------------------------------------------
Kabuktan Soft Link Oluşturma
Soft link hiç bir yere işaret etmeyebilir (dangling softlink). Bazı softlink dosyaları bilgi içerirler ve silinmeleri doğru olmayabilir.

Windows
Dizine junction point oluşturabilir. Junction point sadece iki dosya aynı diskte ise işe yarar. Uzak diskteki dosyaya soft link oluşturmak gerekir.
mklink /j NewFolder OriginalFolder

Linux
Hard link komutu ile aynı. Sadece -s seçeneği kullanılıyor
ln -s original.file new.file

Kabuktan Soft Linki Takip Etme
Örnekte Java'nın kurulum yerini readlink -f ile bulunuyor.
[980@b449 ~]$ readlink -f $(which java)
/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/bin/java

Dosyanın Sembolik Link Olup Olmadığını Kontrol Etme
Java
Java7 ile gelen Files.isSymbolicLink() kullanılabilir.

Apache Commons
FileUtils.isSymlink() kullanılabilir. Yalnız bu metod Windows'ta çalışmıyor sanırım.


API Kullanarak Sembolik Link Oluşturma
POSIX
 int symlink (const char *oldname, const char *newname);


waitpid

Giriş
Parent uygulama başlattığı child uygulamanın bitmesini bekler. Eğer beklemezse ve child sonlanırsa zombie haline gelir.

waitpid metodu
Eğer birden fazla child uygulama başlatılmışsa, herhangi birinin sonlanmasını beklemek için waitpid() kullanılır. Metodun imzası şöyle.
pid_t waitpid(pid_t pid, int *status, int options);
parametreler
İlk parametreye -1 geçilersek, herhangi bir child uygulama için bekleriz. İkinci parametreye NULL geçerek child uygulamanın nasıl çıktığını bilmek istemediğimizi belirtiriz. Üçüncü parametreye WNOHANG geçerek bloke olmak istemediğimizi belirtiriz. Örnek:
/* SIGCHLD handler. */
static void sigchld_hdl (int sig)
{
    pid_t child_pid;

    /* Wait for all dead processes.
     * We use a non-blocking call to be sure this signal handler will not
     * block if a child was cleaned up in another part of the program. */
    while ((child_pid = waitpid(-1, NULL, WNOHANG)) > 0) {
          // child_pid contains the terminated child process' pid
    }
}
Eğer 3. parametre için WUNTRACED kullansaydık şu anlama gelirdi. Child uygulama SIGSTOP ile durdurulsa bile waitpid haberdar olur.

 If the WUNTRACED option is set, children of the current process 
that are stopped due to a SIGTTIN, SIGTTOU, SIGTSTP, or SIGSTOP signal 
also have their status reported.





20 Şubat 2016 Cumartesi

grub

Giriş
grub bir bootloader.

testspeed komutu
Şöyle yaparız.
grub> testspeed /vmlinuz
File size: 3.40MiB
Elapsed time: 1.571 s
Speed: 2.16MiB/s

grub> testspeed /initrd.img
File size: 48.80MiB
Elapsed time: 8.762 s
Speed: 5.57MiB/s


19 Şubat 2016 Cuma

DLL Injection

Giriş
DLL Injection ilginç bir konu. Bir kaç tane farklı yöntemi var. Hepsini anlamadım.

CreateRemoteThread Yöntemi
Anladığım bir örnek şöyle çalışıyor. Bu yönteme aynı zamanda User Mode Hooks via Injected Threads deniyor.
HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procID);

LPVOID arg = (LPVOID)VirtualAllocEx(process, NULL, ...);

int n = WriteProcessMemory(process, .....);

HANDLE threadID = CreateRemoteThread(process, .........);
CreateRemoteThread yönteminde olaylar şöyle işliyor. Bu metod bir başka uygulama içinde thread yaratmak imkanı sunar.

1.Önce OpenProcess ile saldırılacak uygulama'nın handle'ı bulunur.
Burada OpenProcess başka uygulamada hem thread yaratma, hem de belleğine yazma hakkı da elde ediyor.İkinci parametre Inherit Handle anlamına geliyor. TRUE kullanıldığını hiç görmedim.
HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, TRUE, procID);
Sadece yazma hakkını şöyle elde ederiz.
OpenProcess(PROCESS_VM_WRITE,false,firefox_pid);

2. Daha sonra VirtualAlloc ile saldırılacak uygulama içinde bellek ayrılır.
3. Bu belleğe yüklenmesini istediğim DLL'in ismini string olarak yazarız.
WriteProcessMemory ile ReadProcessMemory çok benzer imzalara sahip. ReadProcessMemory metodunun imzası şöyle.

İlk parametre OpenProcess ile elde edilen değer.
İkinci parametre açılan process içindeki bir adres.
Üçüncü ve dördüncü parametreler kendi belleğim ve büyüklüğü.
Son parametre ise okuma işlemi sonucunda kaç byte okunduğudur.
BOOL WINAPI ReadProcessMemory(
    HANDLE hProcess,
    LPCVOID lpBaseAddress,
    LPVOID lpBuffer,
    SIZE_T nSize,
    SIZE_T *lpNumberOfBytesRead
);

4. CreateRemoteThread bir başlama metodu ister. Başlama metodu olarak DLL'imiz içindeki bir metodu veririz.

Yaratılan Thread içinde uygulamayı Task Manager'dan öldürülemez hale getirmek mümkün.
DWORD ProtectProcess(void)
{
    HANDLE hProcess = GetCurrentProcess();
    PACL pEmptyDacl;
    DWORD dwErr;

    // using malloc guarantees proper alignment
    pEmptyDacl = (PACL)malloc(sizeof(ACL));

    if (!InitializeAcl(pEmptyDacl, sizeof(ACL), ACL_REVISION))
    {
        dwErr = GetLastError();
    }
    else
    {
        dwErr = SetSecurityInfo(hProcess, SE_KERNEL_OBJECT, 
                   DACL_SECURITY_INFORMATION, NULL, NULL, pEmptyDacl, NULL);
    }

    free(pEmptyDacl);
    return dwErr;
}




16 Şubat 2016 Salı

passwd

passwd dosyası
passwd dosyası yazısına taşıdım.

Capability
Grup bilgisi aynı zamanda kullanıcının capability'sini de belirler. Capability Windows'ta privilege yani hak, imtiyaz olarak geçer. 3 capability seti vardır.

Capability Sets

Each thread has three capability sets containing zero or more of the above capabilities:

Effective - the capabilities used by the kernel to perform permission checks for the thread.

Permitted - the capabilities that the thread may assume (i.e., a limiting superset for the effective and inheritable sets). If a thread drops a capability from its permitted set, it can never re-acquire that capability (unless it exec()s a set-user-ID-root program).

inheritable - the capabilities preserved across an execve(2). A child created via fork(2) inherits copies of its parent's capability sets. See below for a discussion of the treatment of capabilities during exec(). Using capset(2), a thread may manipulate its own capability sets, or, if it has the CAP_SETPCAP capability, those of a thread in another process.
setcap komutu
setcap komutu ile uygulamaya farklı haklar verilir. Önce capability ismi yazılır. Sonra
e - Effective
i = Inheritable
p- Permitted
seçeneklerinden birisi kullanılır. Daha sonra uygulama ismi verilir.
#setcap cap_net_raw=ep /bin/ping
getcap komutu
Bir uygulamanın capability setini görmek için getcap komutu kullanılır.