Deobfuscate Android Stack Traces Manually

tip

The retrace tool is inside <android-sdk>/tools/proguard/bin folder.

Place the stack traces in a file and run the following command:

1
./retrace.sh [-verbose] /path/to/mapping.txt /path/to/stacktrace.txt

Go modules with private repositories

The following HTTP error may happen when adding a private module (repo) to the project even if your SSH keys are properly configured and you have access to the private repo. Private means it’s not a publicly open project on Github/Gitlab/etc.

warning

GONE 410

The reason for that is that the go mod tool tries to verify the module with its public checksum database, but it cannot find the module listed there (because it’s private).

To skip the check we can declare the repo as private:

1
2
export GO111MODULE=on
export GOPRIVATE=github.com/myusername/myproject

Another option is to disable the checksum database verification:

1
2
3
export GO111MODULE=on
export GOPROXY=direct
export GOSUMDB=off

Pixel 3 Adaptive Brightness Stopped Working

Recently I noticed the adaptive brightness of my phone doesn’t work. Here is the fix:

  1. Open Settings and click Apps and notifications

  2. Click on the link See all 123 apps

  3. Find an app called Device Health Services and click it

  4. Open Storage & cache of the app and click Clear storage

  5. Click on the button Reset adaptive brightness

  6. It seems to work for the moment

SSH Local Port Forwarding

To forward requests coming to a local TCP port to another server [host:port] connected via SSH we can use a config file or direct command line arguments. To use a config file, it should be named config and placed inside the ~/.ssh folder. Here is a sample ~/.ssh/config file with some options:

1
2
3
4
5
6
Host my-ssh-connection
  Hostname 10.20.30.40
  User penkovski
  LocalForward 7070 localhost:8080
  LocalForward 7171 localhost:8181
  ControlMaster auto

This will forward all requests hitting the local (client) TCP port 7070 to the localhost:8080 on the server and all requests for local TCP port 7171 to the localhost:8181 on the server. The above configuration will be used automatically when initiating an SSH connection by the alias:

1
ssh my-ssh-connection

Update an XML node value with Go

In my humble opinion, modifying an XML node value with the Go standard xml package without describing all tags in data structures is not very intuitive. Hence this post is born. There are many ways to do it with their pros and cons. I’ll describe 2 ways. The first is simpler, but loses some XML elements like comments and possibly formatting. The other is more involved but preserves everything from the initial document, including comments and formatting.

Below is the XML document we’ll use as an example and the node we’ll modify is app>description>version. We’d like to set the version value from 1.0 to 2.0. Assume the XML file is called application.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<app>
	<!-- application description -->
	<description>
		<name>My App</name>
		<version>1.0</version>
	</description>
	<!-- developer maintaining the application -->
	<developer>
		<name>Developer Name</name>
		<contacts>
			<email>developer@example.com</email>
			<mobile>+359888888888</mobile>
		</contacts>
	</developer>
	<!-- markets where the app is distributed -->
	<market>
		<googleplay>https://googleplay.com/url</googleplay>
		<appstore>https://appstore.com/url</appstore>
	</market>
</app>

Print stack traces for hanged Go program

If a program using channels or mutexes is stuck because of synchronization problems, we can send an abort signal to kill the process and print the stack traces of currently running go routines to debug where the program might have hanged. Find the PID of the running program with ps and type:

1
kill -ABRT <PID>

JSON unmarshal of time.Duration in Go

The post describes how to unmarshal time.Duration which is not supported by the default JSON unmarshaler, but the example can be used to unmarshal any custom type.

Here is the JSON we’re unmarshaling:

1
2
3
4
{
	"addr": "https://example.com",
	"timeout": "5s",
}

We’d like to convert the 5s value to a time.Duration value corresponding to 5 seconds and get the JSON to unmarshal in the following data structure:

1
2
3
4
type connection struct {
	Addr 	string		`json:"addr"`
	Timeout time.Duration 	`json:"timeout"`
}

One way to do it is to implement the Unmarshaler interface and handle the conversion in our UnmarshalJSON function.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// Unmarshaler is the interface implemented by types  
// that can unmarshal a JSON description of themselves.  
// The input can be assumed to be a valid encoding of  
// a JSON value. UnmarshalJSON must copy the JSON data  
// if it wishes to retain the data after returning.  
//  
// By convention, to approximate the behavior of Unmarshal itself,  
// Unmarshalers implement UnmarshalJSON([]byte("null")) as a no-op.  
type Unmarshaler interface {  
   UnmarshalJSON([]byte) error  
}

Below is the complete example. We unmarshal the JSON into a temprary structure where 5s is a standard string. Then we convert the string to time.Duration vaue and set it in our structure.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package mypackage

import(
	"json/encoding"
	"time"
)

type connection struct {
	Addr 	string 		  `json:"addr"`
	Timeout time.Duration `json:"timeout"`
}

func (c *connection) UmarshalJSON(data []byte) (err error) {
	var tmp struct {
		Addr 	string
		Timeout string
	}
	if err = json.Unmarshal(data, &tmp); err != nil {
		return err
	}

	c.Addr = tmp.Addr
	c.Timeout, err = time.ParseDuration(tmp.Timeout)
	return err
}

Go program design for testing with counterfeiter

counterfeiter is a command-line tool for generating fake implementation of Go interfaces.

One of the best things we can do when writing Go programs is to design our components’ dependencies to be based on local interfaces. By local I mean interfaces which are needed and defined by a given component. Consider the following example: we have a http server, a service component and a database dependency.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package main

func main() {
	// initialize some kind of database
	db := storage.New()
	
	// our service depends on a database
	svc := service.New(db)
	
	http.HandleFunc("/example", svc.Example)
	log.Fatal(http.ListenAndServe(":8080", nil))
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package storage

type DB struct {}

type Data struct {}

func New() *DB {
	return &DB{}
}

func (db *DB) SomeData() (*Data, error) {
	... // return data from database
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package service

type Storage interface {
	SomeData() (*storage.Data, error)
}

type Data struct{
	Value int
}

type Service struct {
	db Storage
}

func New(db Storage) *Service {
	return &Service{db:db}
}

func (s *Service) Example(w http.ResponseWriter, r *http.Request) {
	// do something that requires using the database
	data, err := s.db.SomeData()
	if err != nil {
		...
	}

	// do something with data and write response
	...
}

The service component has a database dependency. It may be any kind of external object - client to another service, a cache/database, message queue, whatever. This dependency is expressed as an interface inside the service package. In effect, the service is telling its initialiser: when you create me, please give me an object which implements my service.Storage interface, cause that’s what I need to execute my functions.

This design has some nice benefits. The service component doesn’t know and care how the storage dependency is implemented. All it knows and cares about is that it has a SomeData() (*storage.Data, error) function. We can supply whatever object we wish to the service, as long as it implements the interface.

Here comes the counterfeiter

Java Random within Range

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// randInt generates pseudo-random number 
// in the range [min...max] inclusive.
public static int randInt(int min, int max) 
{
    Random random = new Random();

    // nextInt is exclusive of the top value, 
    // so add 1 to make it inclusive
    return random.nextInt((max - min) + 1) + min;
}

Git SSH Authentication

If we want to use different authentication keys for a particular Git repo, we can edit the config file of the repo and add the sshCommand setting.

Navigate to the repository’s Git configuration directory:

1
cd /path/to/repo/.git

In the folder there’s a file called config. We are interested in the core section. To use a particular SSH key for Git, we would write the command as shown below. Replace the name of the key file with your own.

1
2
3
4
5
[core]
	...
	...
	...
	sshCommand = ssh -i ~/.ssh/my_custom_git_key