Wednesday, November 18, 2020

Linux on XPS 13 9310 (Late 2020)

 I was able to get the 9310 non-Developer Edition at a pretty good discount, but I couldn't find anything online about installing Ubuntu on it vs the pre-installed image on the Developer Edition.

BLUF: Ubuntu Linux works fine on the non-Developer Edition of the XPS 13 9310.

- When booting from the Live USB, the Intel wireless device did not work.  This may have just been a glitch because the next time I booted from a Live USB, the wireless worked just fine.  In both cases it worked after installation.

- When installing, you'll probably want to choose to install non-free drivers to ensure that the Iris graphics work.  It will prompt you to create a Secure Boot password.  This is different than the disk encryption key or login password.  When booting for the first time, you'll get a prompt asking you to enrol a new key.  I'm unsure if it's always the British spelling, or if my location somehow influenced that.  You do need to enrol the key by entering the password you created, otherwise a kernel without the proprietary drivers will boot and you will be sad.

- Other than needing to ensure that the proprietary drivers are added, Xubuntu 20.04.1 worked great out of the box.  I suspect there are some improvements to be made in the kernel (I'm currently on 5.6.0) for the 11th gen CPU / Iris graphics because the battery life is terrible.  It's drawing more than 10W at idle with an expected runtime of only 5 hours.  I expect this to be the same on other Ubuntu flavours, but I can't speak for other distros.

- Unlike some others, I found the backlight plenty bright, even on low settings.  The keyboard backlight is also quite strong and I rarely want more than the "low" option there.


Correction: I stated above that baseline power draw was around 10W with only 5 hours of expected battery life.  As of a few days later, I'm seeing closer to 9.5 hours of expected runtime with typical discharge rates closer to 6W at idle/light load.

Thursday, August 20, 2020

Linux on Asus Zenbook 13 UX325

I recently bought a Zenbook 13 in a leap of faith as there weren't any reviews online indicating how well the new 10th gen (Ice Lake) model handles Linux.

I originally tried booting Ubuntu 18.04 LTS, but the 4.x kernel didn't seem to support the Ice Lake graphics as all I got as a 800x600 resolution.  Additionally, the Intel wireless didn't work.  A 20.04 live USB fixed the graphics, but still no wi-fi.  Fortunately, after installing offline and a reboot the wireless worked.

A day into use, there appear to be no significant issues with Ubuntu out of the box.

The number pad on the touchpad does not work, which is a shame.

Thursday, July 2, 2020

Dropbox Stuck Syncing on Linux

 Sometimes, the Dropbox client starts and hangs while reporting "Syncing..." in the status tray.  "dropbox status" unhelpfully returns "Syncing...".

Try running this:

echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf; sudo sysctl -p

Monday, June 15, 2020

Source Code vs. Machine Code

An excerpt from my upcoming book:

Here is an example of source code:

```
int add(int a, int b) {
    int c = a + b;
    return c;
}
```

This is a function that takes two numbers (integers in this case), adds them, and returns the sum.  Computers, of course, read code in zeros and ones.  Raw data (the zeros and ones) that correspond to instructions is called machine code, and here is what it looks like:

```
10101011000100111100101100000111110110000010000111010000110010
10000000000000000000000000000010110110000000110100000000000000
00010001011010101010000100010001011010001010000110000000001110
10000100010010100010111111100100010110100010111111100110010011
1000011
```

Got it, right?  Good, because if you don't understand that machine code, you should probably just give up on this cyber thing.

Totally kidding.  No one, even experts, are expected to be able to read binary.  People have to program computers somehow, though.  Fortunately, there is a language to define computer behavior that can be read by humans: assembly language.  An example of assembly code is below:

```assembly
push ebp
mov ebp, esp
sub esp, 16
call __x86.get_pc_thunk.ax
add eax, OFFSET FLAT:_GLOBAL_OFFSET_TABLE_
mov edx, DWORD PTR 8[ebp]
mov eax, DWORD PTR 12[ebp]
add eax, edx
mov DWORD PTR -4[ebp], eax
mov eax, DWORD PTR -4[ebp]
leave
ret
```

Each line of assembly code consists of an instruction and zero or more arguments to that instruction.  Let's consider the third line above, `sub esp, 16`.  The 'esp' refers to a register, which is a physical part of the processor that stores a number.  If you were a computer and were doing math on your hands, you might say that each hand is a register that can store a number between zero and five.  This line of assembly is telling the processor that it should subtract 16 from the register esp.

It is actually quite easy to convert between assembly language and machine code, because assembly is intended to be a human readable version of machine code.  When Steve Wozniak wrote some of the first software for Apple computers, he did so in math class by writing the assembly in his notebook.  Then, for each line, he looked up in a table for the corresponding hexadecimal and wrote that in the margin.  Since it just requires a table lookup to go between machine code and assembly language, we will use assembly as a proxy for what the machine is actually doing.

Fun fact: the software mentioned above was a BASIC compiler for the Apple I.  Wozniak was inspired to write it because he was annoyed at all the attention some jerk named Bill Gates was getting at the Homebrew Computer Club meetings for writing a BASIC compiler for an earlier Altair computer.

Tuesday, April 21, 2020

How to Make BibLaTeX Actually Work

I had a lot of annoying, surprisingly difficult to Google (or Duck) errors when trying to do automatic bibliography management with LaTeX.  Some important things that I learned are:
  • BibTeX and BibLaTeX are two different things.
  • BibLaTeX is the LaTeX package for formatting your citations.
  • BibTeX is a separate program for converting a human-readable .bib file into the database used by a LaTeX processor like pdflatex.
  • Biber is another external processor, like BibTex.  I understand that Biber is actively developed and probably better for most use cases
I got this error when first trying to use BibLaTeX.

!LaTeX Error: File `biblatex.sty' not found

I needed to install the packages texlive-latex-extra and biber.  For your copy-pasting convenience:
sudo apt install texlive-latex-extra biber
Then, you need to run three commands to make your bibliography appear.
pdflatex my_file.tex
biber my_file
pdflatex my_file.tex
Note that unlike pdflatex which allows you to use the name with or without the extension (it will automatically append .tex if you don't), you need to run biber with the filename minus the extension.

This was all on Ubuntu 18.04 or a derivative such as Xubuntu or Gallium OS.

How to Not Mess Up your Python Dependencies Using Virtualenv

Don't you hate it when you try to pip install something and you get some super annoying error?  Me too.  The solution is a virtual environment.
virtualenv -p python3 venv
 This command creates a virtual environment in the directory "venv" under the current directory.  The command specifies python3 as opposed to 2, because it's 2020 and you should be using Python3.

Then, activate the virtual environment:
source venv/bin/activate
You should now see "(venv)" prepended to your command line.

To install something, just use "pip install [PACKAGE]".  You don't need to specify a directory target or use pip3, because the virtualenv is already set!

If you have a requirements document, you can install all of them with "pip install -r requirements.txt".

Hopefully I'll update this post with some specific error messages to make it more useful in search engine results.

Wednesday, April 8, 2020

Python - Get relative filenames recursively

I was working on a script where I needed to get all of the filenames in a directory and sub-directories, and it was a lot more convenient to use relative paths.  I didn't find exactly that via Google (or DuckDuckGo), but this works:

dir_files = []
for root, dirs, filenames in os.walk("target"):
    for filename in filenames:
        path = os.path.join(root, filename)
        rel_path = os.path.relpath(path, "target")
        dir_files.append(rel_path)
This gets all of the filenames relative to "target" - so if we are in /something/, the file "/something/target/my_directory/my_file" will be listed as  "my_directory/my_file".

Of course, this can be done with list comprehensions as well but I left it in loop form because I think that's more readable.

Tuesday, January 28, 2020

Ubuntu Linux - Run jar for high DPI display

If you run Ubuntu (or a derivative) with a high DPI display (for me, a 4K laptop screen), it can be annoying when you run a Java program such as Ghidra and the user interface is tiny.

Run this to launch an executable jar, scaling all UI elements by 2x:
java -Dsun.java2d.uiScale=2.0 -jar my_program.jar

Automatic Security Updates on Ubuntu


Run the following to install the unattended-upgrades package:
sudo apt update
sudo apt install unattended-upgrades
Now edit the file /etc/apt/apt.conf.d/50unattended-upgrades. Ensure that the line with "${distro_id}:${distro_codename}-security" is uncommented.

You may also want to uncomment "Unattended-Upgrade::Automatic-Reboot "true";" further down.

Saturday, August 3, 2019

Packages Installed by Default on Kali Linux

I recently needed to look up whether gcc was installed by default on Kali and I didn't find an easy way to do that.

Here's a list of all of the packages installed by default on Kali as of the 2019.2 version: https://pastebin.com/raw/PzpEaYfS

Note that I used the Kali premade VM from Offensive Security, which installs things such as open-vm-tools in addition to the normal Kali rolling release.

In case you're curious what command I used to get this list:
dpkg --get-selections | cut -f1

Sunday, March 17, 2019

Aruba QuickConnect Onboard Wizard on Ubuntu

The Aruba QuickConnect Onboard Wizard theoretically supports Linux hosts.  If you download the utility from a browser reporting Linux as the host OS, you will get a 47 MB shell script that is mostly a binary blob.  This self-extracts to "/tmp/quickconnect" and runs a binary application from there.  I got a segfault every time that I ran it with no useful error messages.  Unfortunately, the binary is stripped and was quite difficult to reverse - I didn't make in progress trying to debug it. 
It seems that the issue is with one of the libraries that is used only when the Qt app is running in GTK fallback mode.  I got the segfault in standard GNOME Ubuntu 18.04 and in Xubuntu 18.04, but it did not occur in Kubuntu 18.04.  Unfortunately, simply installing kde-desktop on another flavor and running the Qt from inside a KDE session did not seem to work.  My ultimate solution was to install Kubuntu on the relevant device, onboard, and then install another desktop environment.  I prefer to not use KDE due to a bug where apps (to include LibreOffice) are not recognized as an input window by fcitx and pinyin input is an absolute requirement for me.

For some strange reason, the Onboard Wizard failed several times and then worked correctly on Gallium OS on my Chromebook, despite the fact that Gallium OS uses XFCE.

One other item of note is that the Onboard Wizard fails to properly switch from the onboarding network for the 802.11x network.  The wizard will stop at this step, but you can just disconnect and connect to the correct network manually.

TODO: Update this post with the exact error message and screenshots the next time that I get it.

Monday, October 8, 2018

Installing Ubuntu on Dell XPS 15 9560

The XPS 15 9560 is a great laptop and Linux works quite well on it, but it needs some tweaks out of the box, mostly to deal with the discrete NVIDIA GPU.  Here are the steps I took to get Ubuntu 18.04 (well, Kubuntu actually) working.

The desired end state is a dual-boot setup with Windows 10 and Linux, with some sort of discrete graphics switching available from the Linux OS.  I use Linux as the primary OS and rarely need the dedicated GPU as battery life is usually a higher priority.

  1. In the BIOS settings, disable secure boot,.
  2. Boot from the Ubuntu installation flash drive.  Make sure you choose the UEFI boot option, not Legacy!
  3. Hit 'e' when you get to the grub prompt.  This brings up an editor for the grub command line, but it will be very laggy.  To get around this when we actually boot, add 'nomodeset' after 'quiet splash'.
  4. Hit F10 to boot with the modified command line.
  5. Run the Ubuntu installer.  I made a 16 GB swap space at the end of the disk with a 180 GB ext4 partition before that for the mount point '/'.  Make sure the actual internal SSD is the device selected for bootloader installation.  It's way easier to make grub boot to Windows than to make the Windows bootloader see a Linux OS.
  6. When you reboot into the actual installed OS, follow the same steps to add 'nomodeset' to the boot command line.  Otherwise the system will be unusable.
  7. The open-source nouveau driver for the GTX 1050 does not work well, at least for me, so we won't be using it. Open "Driver Manager" within Ubuntu.  It will scan your system and determine that closed-source drivers are available for the 1050.  Select the NVIDIA driver.  As of when I'm writing this, the current release is 390 which is quite good.  It will take a bit to download and install.
  8. To select which GPU to use (integrated or discrete), open the Nvidia X Server Settings.  Under 'Prime Profiles', you can select between NVIDIA and Intel GPUs.  You'll need to reboot (or at least logout and log back in) every time you do this.  If you want to verify which GPU is in use, you can run glxgears.  It should return around 60 fps on integrated and many thousands on the discrete card.
  9. For some reason, Ubuntu still loads the nouveau driver as a fallback.  This prevents the laptop from suspending properly and is generally a huge pain.  To disable it, add 'nouveau.modeset=0' to the default command line in /etc/default/grub.  The line should look like this:
    GRUB_CMDLINE_LINUX_DEFAULT="quiet splash nouveau.runpm=0 nouveau.modeset=0"
    Once that line has been added, reload the grub config.
    sudo update-grub
  10.  Some other things that might be helpful to do:
    • Change the desktop scaling to 1.5x, which makes the 4K display more usable
    • Change the touchpad settings to allow tap to click
    • Also consider the post-install script at jamesbrahm.us/files/setup.bash
Edit: Thanks to Maddy Tung for a correction to the link in this post.

Wednesday, April 18, 2018

Simple Buffer Overflow Tutorial

This is intended to be an accessible, simple tutorial for to explain how a buffer overflow works.

Assumptions:
- You have some basic programming knowledge
- You have a Ubuntu 16.04 LTS setup or similar

First, we are going to create our vulnerable program.  It doesn't need to be fancy, it just needs to accept user input in an insecure way.

Create a file called hackme.c and put this C code in it:
#include <stdio.h>
void win() {
        printf("This should never be printed.\n");
}
int main(int argc, char** argv) {
        char user_in[16];
        printf("Enter a string: ");
        scanf("%s", user_in);
        printf("Done.\n");
}
Let's go line by line through this and see what it does.

#include <stdio.h>
This line, and any that starts with a "#" is a preprocessor directive.  It instructs the preprocessor to make use of the stdio.h file, which contains the function definition for printf and scanf, which we plan to use.  If you want to see what this file looks like, you can look at it manually at /usr/include/stdio.h.

void win() { ...
This declares a function called win.  The void in front indicates that it does not return anything, and the empty parentheses indicate that it does not take any arguments.  The curly braces after each function declaration bound what code is included in that function.

printf("This should never be printed.\n");
This line makes use of the printf command, which formats and prints data.  It is similar to print functions in other languages.

int main(int argc, char** argv) { ...
This is a function declaration like above, but for our main program.  By calling this function main, we are telling the compiler that this should be run as soon as the user starts the program.  The "int" at the beginning says that we will return an integer.  By convention, main functions return an integer which represents the status code of the program upon exit.  The two arguments to the main function allow us to access command line arguments.  More on this later.

char user_in[16];
Now it gets interesting.  This creates an array of type "char" for character called "user_in" with a length of 16.  Since a character is 1 byte, this is going to allocate a space of 16 bytes on the stack.  At the assembly level, the stack pointer is going to be decremented by 16 (the stack grows downward in memory space).  The variable name user_in is essentially just a convenient human shortcut to represent the offset from the base pointer to this free space of 16 bytes on the stack.

Question: What is in this 16 byte space on the stack?
Answer: That is undefined!  We just allocated space, so whatever was in that spot in memory is likely still there.  You should never rely on memory space being "clean" or zeroed out.

 scanf("%s", user_in);
This is the last function we haven't talked about.  Scanf is going to look at stdin (keyboard input in this case) for something that fits the format of a string ("%s").  It is then going to write that string to user_in.  Keep in mind that user_in is a pointer to the 16-byte area in memory that we allocated.

Now we'll compile and run our vulnerable program.
gcc hackme.c -o hackme
./hackme
You can try entering any short string, such as your name.  It should simply print "Done."   Whatever string you are entering is being written in the 16 byte space we allocated earlier.  But wait, what happens if we enter a string longer than 16 characters?  Try it!

You can always run this program and then type or copy-paste your input manually, but you can use Python to automate your input:
python3 -c 'print("A"*37)' | ./hackme
Using the -c argument, we are running Python code on the command line.  The print statement is printing the string "A" 37 times.  Isn't Python cool?

If you enter a long enough string, you should get this message: "*** stack smashing detected ***"
Wait a second, what is the stack?  What does smashing it mean?

[There will later be a stack tutorial here]

Our stack smashing attack was detected because the compiler puts special values called canaries on the stack.  The compiler also inserts code to check (just before function return) whether these canaries have been modified.  If they have been modified, something's fishy.  One way to get around stack canaries is to figure out where they are and what values are supposed to be.  We can then ensure when we overwrite the stack we overwrite those with the same values!  For now, though, we'll just recompile without these.  We'll also be using 32-bit from now on.
gcc -m32 hackme.c -fno-stack-protector -o hackme
To make that work you may have to run this:
sudo apt-get install lib32z1 lib32ncurses5 gcc-multilib
 Putting our 37 "A"s into the program again, you should get a segmentation fault!  This is exciting!  Breaking stuff is usually the first step to exploiting it.

0804848b

Sample Cuckoo Malware Analysis Report

Here's a sample Cuckoo report so you can easily see what the output looks like.  This is for a copy of notepad.exe I found online somewhere... probably not malware.

This was run using a pretty basic Cuckoo setup with a Windows 10 VM running under VirtualBox.

https://raw.githubusercontent.com/novabrahm/ml499/master/notepad_sample.json

Tuesday, April 17, 2018

Cuckoo Malware Analysis Framework Tutorial

Note: This is horribly incomplete and very much a work in progress.  I'm posting in regardless so someone with the same error messages might find help.

I had to set up the following iptables rules to get routing to work between the host and the guest.
iptables -t nat -I POSTROUTING -s 192.168.56.0/24 -j MASQUERADE
iptables -P FORWARD ACCEPT
iptables -t nat -P POSTROUTING ACCEPT
Now you need to actually install the Cuckoo agent on the VM.  You can find the agent client in the Cuckoo Working Directory under /agent, called agent.py.  Copy this to the VM and run it.

This is a good time to snapshot your VM for when you inevitably break it.  Not that I know that from experience.


Activate the virtual environment:
virtualenv cuckooenv
./cuckooenv/bin/activate
Because I always start Cuckoo with the command:
cuckoo
To download signatures, you should be able to run "cuckoo community".  It should download and install everything automatically, but it kept choking on the 16 MB download for me.  You can also wget it manually:
 wget https://github.com/cuckoosandbox/community/archive/master.tar.gz
cuckoo community --file master.tar.gz
To run cuckoo, run "cuckoo".
To submit a task for analysis, run "cuckoo submit Notepad.exe" or whatever your binary name is.

I got a tcpdump error:
CuckooOperationalError: Error running tcpdump to sniff the network traffic during the analysis; stdout = '' and stderr = 'tcpdump: vboxnet0: That device is not up\n'. Did you enable the extra capabilities to allow running tcpdump as non-root user and disable AppArmor properly (the latter only applies to Ubuntu-based distributions with AppArmor, see also https://cuckoo.sh/docs/faq/index.html#permission-denied-for-tcpdump)?
I went to that FAQ and disable AppArmor for tcpdump:
 sudo aa-disable /usr/sbin/tcpdump
I got this error:
ERROR: /sbin/apparmor_parser: Unable to remove "/usr/sbin/tcpdump".  Profile doesn't exist
It turns out this fixed the issue instead:
sudo setcap cap_net_raw,cap_net_admin=eip /usr/sbin/tcpdump
After fixing the tcpdump issue, I'm still getting some IP configuration error:
ERROR: Error processing task #3: it appears that the Virtual Machine hasn't been able to contact back to the Cuckoo Host. There could be a few reasons for this, please refer to our documentation on the matter: https://cuckoo.sh/docs/faq/index.html#troubleshooting-vm-network-configuration
If you get this error, first check to make sure that the host and the guest can ping each other.  In my setup, the host was 192.168.56.1 and the guest was 192.168.56.101.

Somehow, Windows Firewall turned itself back on for public networks so I had to turn that off again.  I could then ping back and forth, but I was still getting this error because I had failed to set the result server IP in cuckoo.conf.

To do this, find the line in ~/.cuckoo/conf/cuckoo.conf with "ip = " under the "[resultreserver" section.  It should be set to the host IP, 192.168.56.1 in my case.