Sunday, March 7, 2021

Bringing back life to this blog

Welcome 2021!

My last posts where 2 years ago. There where lots of happenings in my life so I was not able to continue creating content on this blog.

On those posts, I focused mainly on content based from experience my 8 yrs experience as a DevOps/Sys Administration work.

Now things have changed. I'm focused towards area of Cyber Security. I know this is a large scope but I'm starting first at the basic level like malware analysis and reverse engineering.

So from time to time you might see me posts very low level programing stuffs. But I'll still be posting DevOps related content since that's still day job.

So enjoy and stay tune for upcoming contents!

Tip in moving data to memory

In this code, we want to replace a WORD on in myVar by 3.


.data
myVar DWORD 12345678h

.code
mov ax,3
mov WORD PTR myVar+2,ax
mov eax,myVar


The question is: which WORD will be replaced?


If we look closely, myVar has 2 WORD parts.


1234h - 1st WORD
5678h - 2nd WORD


Remember that this will be store in little endian format in memory so the layout would be:


78 -- 1 byte storage
56 -- 1 byte storage
34 -- 1 byte storage
12 -- 1 byte storage


In our code above, we used PTR to replace the 2nd word of myVar. From the layout, the 2nd WORD is:


34 -- 1 byte storage
12 -- 1 byte storage


So if we run the code, the resulting value of EAX is:


00035678h

MOV Operator

  • Copies data from source operand to destination operand

MOV   destination, source


  • Cannot copy data from smaller to larger operand. For example if you are going to copy 16-bit data to a 32-bit register, set first the 32-bit register to 0 and use its lower 16-bit part.

.data
count WORD 1 ; 16-bit value

.code
mov ecx,0    ; 32-bit register
mov cx,count ; lower 16-bit part


  • But if you use immediate operands (no data labels) and you copy a smaller to a larger operand, it will work. The upper bits of destination will be cleared out (equal to 0).

.code
mov eax,0ffh
; eax = 0x000000ff


  • If the source operand is a data label, it copies data from that memory location to the destination operand. To copy only the memory address (and not the data), use offset operator.

mov eax,offset myVal ; copies memory address 0x00B8102B to eax
mov eax,myVal       ; copies data contained in 0x00B8102B to eax
mov eax,[myVal]     ; same as above


  • If the source operand is a register and contains a memory address, you must dereference it if you want to get the actual data.

mov esi,offset myVal ; copies memory address 0x00B8102B to esi
mov eax,esi          ; copies memory address 0x00B8102B to eax
mov ecx,[esi]        ; copies data located in memory address 0x00B8102B to ecx


MOVZX (MOV with zero-extended)

  • Allows directly moving smaller operand to larger operand by adding 0’s on remaining part (like a padding)


.data
byteVal BYTE 10001111b  ; byte is 8 bits 

.code
movzx ax, byteVal.  ; ax is 16-bit


  • This can only be used on the following type of operands



  • If higher bits of destination register has contents, those will be overwritten by 0.

MOVSX (MOV with sign-extended)


  • Similar to MOVZX
  • The destination operand MSB is set to the MSB of the source operand

.data
byetVal BYTE 10001111b

.code
movsx ax, byteVal


Offset Operator

  • Offset represents the distance of a data label from beginning of data segment
  • Let’s say we have this data definitions.

.data
bVal BYTE 10h
wVal WORD 2030h
dVal DWORD 40506070h
dVal2 BYTE ABH


  • The 4 variables above will be layed out in memory in this manner. bVal offset is 0 meaning it starts directly from data segment. On the other hand, wVal offset is 1 because it needed to allocate 1 byte of storage for the previous data (which is bVal; a BYTE) first before it can be positioned in memory. The from there it will be allocated 2 bytes since its a WORD. Same true for dVal2 but in this case it needs to allocate 4 bytes of space first because the previous data is a DWORD.



  • Offset also represents the memory location where the data resides. So if we would convert the above diagram into arbitrary memory addresses, it can look like this. That means that bVal is located at exactly address 00404000h while wVal is at address 00404001h.



  • Given the above statements, offset operator can be used to determine the location of data or the memory address.

.data
myVal BYTE 10h

.code
mov eax,offset myVal


Varying destination operand sizes

  • If we have this data definition,

myBytes  BYTE 10h,20h,30h,40h


  • If we get the offset of first element of array, put it in a byte-size register then it seems very straightforward.

mov esi,offset myBytes
mov al,[esi]            ; al = 10h


  • But if we change the destination operand into a word-size register, the behavior changes.

mov ax,[esi]        ; ax = 2010h


  • That happened because the mov operation tries to fill up the remaining 1-byte space on destination operand by getting the additional 1-byte data after the first element on the offset which in this case it is the second element 20h.

Saturday, March 16, 2019

Restic for Deduplicated backups!


Restic
------

- Uses deduplication for fast and efficient backups.
- Written in go.
- Runs on Linux and Windows.
- Can be used in cloud, remote, or local backups.

Initializes as backup location
restic -r /opt/backups init
Takes a backup
restic -r /opt/backups --verbose backup /home/john/myfiles
List backups as snapshots
restic -r /opt/backups snaphots
Restore a backup to a target directory
restic -r /opt/backups restore <snapshot ID> --target /tmp/restored-data
Restores latest backup
restic -r /opt/backups restore latest --target /tmp/restored-data
Compares differences between 2 snapshots
restic -r /opt/backups diff <snapshot ID 1> <snapshot ID 2>

Sources:

Monday, February 25, 2019

Cgroups


Basic Information
-----------------

- Kernel feature that limits CPU, memory, Disk I/O and network usage of
  processes.
- More sophisticated than `ulimit`.
- Some resources that can be controlled via cgroups:
    a. cpu share
    b. cpu number to use
    c. memory
    d. and many more

Controllers
-----------

memory
limits memory usage
cpuacct
monitors cpu usage

Tutorials
---------

Commands to check
# Check process cgroup membership
ps -o cgroup <PID>
Creating cgroups manually (not persistent)
1. Install packages
yum install libcgroup libcgroup-tools
 
2. Create group under memory controller
mkdir /sys/fs/cgroup/memory/foo

3. Create this shell script
#!/bin/bash

while true; do
  echo hello > /dev/null
  sleep 1
done

4. Run script in background to emulate memory consuming process
bash test.sh &

5. Apply memory limit under "foo" group
echo 5 > /sys/fs/cgroup/memory/memory.limit_in_bytes

6. Get PID of script and include it under "foo" group
echo (pgrep -f test.sh) > /sys/fs/cgroup/memory/foo/cgroup.procs

7. Notice that script was killed by OOM
journalctl | tail
Creating cgroups using "libcgroup" (not persistent)
1. Install packages
yum install libcgroup libcgroup-tools
 
2. Create group under memory controller
cgcreate -g memory:foo

3. Create this shell script
#!/bin/bash

while true; do
  echo hello > /dev/null
  sleep 1
done

4. Run script in background to emulate memory consuming process
cgexec -g memory:foo test.sh &

5. Apply memory limit under "foo" group
echo 5 > /sys/fs/cgroup/memory/memory.limit_in_bytes

6. Notice that script was killed by OOM
journalctl | tail
Enabling persistent configurations
1. Update /etc/cgconfig.conf
 
group foo {
  cpu {
    cpu.shares = 100;
  }
  memory {
    memory.limit_in_bytes = 5;
  }
}

2. Enable service
systemctl enable --now cgconfig

3. Run a program under cgroup control
cgexec -g memory:foo test.sh &


Thursday, February 7, 2019

Setup single-master cluster using kubeadm

In this tutorial, we will setup a 1 master 1 worker kubernetes cluster.
The machines are provisioned using Vagrant (not covered in this tutorial) and
are both running Centos 7.6. Make sure to add a second IP on the machines. We
will use them as the node IPs.

1. Prepare 2 VM (1 master and 1 worker).
kube1 --> master
kube2 --> node
2. Disable swap on all machines.
swapoff /swapfile
sed -i 's/\/swapfile none swap defaults 0 0/# \/swapfile none swap defaults 0 0/' /etc/fstab
3. Disable firewall on all machines.
systemctl disable --now firewalld
4. Install kubeadm and kubelet on all machines.
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kube*
EOF
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
yum install -y kubelet kubeadm kubectl --MarkdownEditing=kubernetes
systemctl enable kubelet && systemctl start kubelet
5. Install docker on all machines.
yum install yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum update && yum install docker-ce-18.06.1.ce
mkdir /etc/docker
cat > /etc/docker/daemon.json <<EOF
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ]
}
EOF
mkdir -p /etc/systemd/system/docker.service.d
systemctl daemon-reload
systemctl start --now docker
6. Go to master and initialize it. We will use Calico as our pod network
plugin so we need to specify the pod CIDR during initialization. We will use
also the node IP of the master to advertise the API server endpoint.
kubeadm init --pod-network-cidr=192.168.0.0/16 --apiserver-advertise-address=192.168.50.101
7. You should have an output similar to this and make sure to copy the
bootstrap command. You will use that in joining other nodes to the cluster.
[...]
[bootstraptoken] Using token: <token>
[bootstraptoken] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstraptoken] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstraptoken] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy
Your Kubernetes master has initialized successfully!
To start using your cluster, you need to run (as a regular user):
  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the addon options listed at:
  http://kubernetes.io/docs/admin/addons/
You can now join any number of machines by running the following on each node
as root:
  kubeadm join 192.168.50.101:6443 --token wwdq15.mu6fjqngw9en8i07 --discovery-token-ca-cert-hash sha256:3ecf97042860331e2cc5df8b72a94f7bdd1c77024aa0ea8ee59c422139a3a86f
8. Still on the master node, setup your kubeconfig file so you can now start
interacting with the master.
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/conf
9. Once kubeconfig file is setup, check the status of the node and the pod.
There should be only 1 node running and coredns pods should not be running at
this point since we haven't install calico yet.
kubectl get nodes
kubectl get po --all-namespaces
10. Install calico.
kubectl apply -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/installation/hosted/rbac-kdd.yaml
kubectl apply -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/installation/hosted/kubernetes-datastore/calico-networking/1.7/calico.yaml
11. Go to the worker node and join it to the cluster.
kubeadm join 192.168.50.101:6443 --token wwdq15.mu6fjqngw9en8i07 --discovery-token-ca-cert-hash sha256:3ecf97042860331e2cc5df8b72a94f7bdd1c77024aa0ea8ee59c422139a3a86f
12. Wait for few minutes and there will now be 2 kubernetes nodes available.
kubectl get nodes

If you want an automated way, visit this github repo.